阅读大型mongodb数据

时间:2017-09-28 09:12:04

标签: java mongodb hadoop morphia

我有一个java应用程序需要从MongoDB 3.2读取大量数据并将其传输到Hadoop。

此批处理应用程序每天运行6次,每4小时一次。

数据规范:

  • 文件:每次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?

2 个答案:

答案 0 :(得分:1)

您的问题出在asList()电话

这会强制驱动程序遍历整个游标(80,000个文档,几个Gigs),保留所有内存。

无论批量大小是什么,

batchSize(someLimit)Cursor.batch()在遍历整个光标时都不会有帮助。

相反,您可以:

1)迭代光标:List<MYClass> datalist = datasource.getCollection("mycollection").find()

2)一次读取一个文档并将文档送入缓冲区(让我们说一个列表)

3)对于每1000个文件(比如说)调用Hadoop API,清除缓冲区,然后重新开始。

答案 1 :(得分:0)

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);
  }