我有一个java应用程序需要从MongoDB 3.2读取大量数据并将其传输到Hadoop。
此批处理应用程序每天运行6次,每4小时一次。
数据规范:
目前我正在使用 MongoTemplate 和 Morphia 来访问MongoDB。 但是,在使用以下内容处理此数据时,我收到OOM异常:
List<MYClass> datalist = datasource.getCollection("mycollection").find().asList();
阅读此数据并填充到Hadoop的最佳方法是什么?
MongoTemplate::Stream()
并逐一写信给Hadoop?batchSize(someLimit)
并将整个批处理写入Hadoop?Cursor.batch()
并逐个写入hdfs?答案 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);
}