读取大型mongodb数据

lo8azlld  于 2021-06-02  发布在  Hadoop
关注(0)|答案(2)|浏览(383)

我有一个java应用程序,需要从MongoDB3.2读取大量数据并将其传输到hadoop。
此批处理应用程序每4小时运行一次,每天运行6次。
数据规格:
文件:每次80000份(每4小时一次)
大小:3gb
目前我正在使用mongotemplate和morphia来访问mongodb。但是,当使用以下方法处理此数据时,会出现oom异常:

List<MYClass> datalist = datasource.getCollection("mycollection").find().asList();

读取这些数据并填充到hadoop的最佳方法是什么? MongoTemplate::Stream() 一个接一个的写hadoop? batchSize(someLimit) 并将整个批处理写入hadoop? Cursor.batch() 一个接一个地写hdfs?

hzbexzde

hzbexzde1#

这个 asList() 调用将尝试将整个mongodb集合加载到内存中。正在尝试使内存中的列表对象的大小大于3gb。
使用游标迭代集合将解决此问题。您可以使用datasource类来实现这一点,但我更喜欢morphia为dao类提供的类型安全抽象:

class Dao extends BasicDAO<Order, String> {
    Dao(Datastore ds) {
      super(Order.class, ds);
    }
  }

  Datastore ds = morphia.createDatastore(mongoClient, DB_NAME);
  Dao dao = new Dao(ds);

  Iterator<> iterator = dao.find().fetch();
  while (iterator.hasNext()) {
      Order order = iterator.next;
      hadoopStrategy.add(order);
  }
kpbwa7wx

kpbwa7wx2#

你的问题在于 asList() 呼叫
这迫使驱动程序遍历整个游标(80000个文档,几个gig),将所有文档都保存在内存中。 batchSize(someLimit) 以及 Cursor.batch() 在遍历整个游标时,不管批大小是多少,都没有帮助。
相反,您可以:
1) 迭代光标: List<MYClass> datalist = datasource.getCollection("mycollection").find() 2) 一次读取一个文档,并将文档输入缓冲区(比如说一个列表)
3) 对于每1000个文档(比如说)调用hadoopapi,清除缓冲区,然后重新开始。

相关问题