我有一个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?
2条答案
按热度按时间hzbexzde1#
这个
asList()
调用将尝试将整个mongodb集合加载到内存中。正在尝试使内存中的列表对象的大小大于3gb。使用游标迭代集合将解决此问题。您可以使用datasource类来实现这一点,但我更喜欢morphia为dao类提供的类型安全抽象:
kpbwa7wx2#
你的问题在于
asList()
呼叫这迫使驱动程序遍历整个游标(80000个文档,几个gig),将所有文档都保存在内存中。
batchSize(someLimit)
以及Cursor.batch()
在遍历整个游标时,不管批大小是多少,都没有帮助。相反,您可以:
1) 迭代光标:
List<MYClass> datalist = datasource.getCollection("mycollection").find()
2) 一次读取一个文档,并将文档输入缓冲区(比如说一个列表)3) 对于每1000个文档(比如说)调用hadoopapi,清除缓冲区,然后重新开始。