2017-09-28 60 views
5

我有一個java應用程序需要從MongoDB 3.2讀取大量數據並將其傳輸到Hadoop。讀取大型mongodb數據

此批處理應用程序每天運行6次,每4小時運行一次。

數據規格:

  • 文件:80000在一個時間(每4小時)
  • 尺寸:3GB

目前我使用MongoTemplate嗎啡在爲了訪問MongoDB。 不過我用這個處理數據時得到一個OOM異常如下:

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

什麼是讀取該數據並填充到Hadoop的最好方法是什麼?

  • MongoTemplate::Stream()並且一個一個地寫入Hadoop?
  • batchSize(someLimit)並將整批寫入Hadoop?
  • Cursor.batch()並寫入hdfs一個接一個?

回答

1

你的問題就出在asList()電話

這迫使司機在整個光標迭代(80,000文檔很少演出),保持所有在內存中。

batchSize(someLimit)Cursor.batch()在遍歷整個遊標時,無論批量大小是多少,都需要幫助。

相反,您可以:

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

2)讀取文件一次一個和飼料的文件到緩衝區(比方說,一個列表)

3)對於每1000個文檔(比如說)調用Hadoop API,清除緩衝區,然後重新開始。

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