如何使用nodejs

时间:2016-10-31 10:12:47

标签: node.js mongodb batch-processing

MongoClient.connect(url, function(err, db) {
var batch = db.collection("chatmessage").initializeOrderedBulkOp();
//var batch = db.collection("chatmessage").db.collection.initializeUnorderedBulkOp()
var messageNum=0;
var chatmessage = null;
var count =0;
for (var i = 0;i<300;i++){
  messageNum = getMessage();//value from 1~500000;
  for(var j = 0;j<messageNum;j++){
     count++;
     chatmessage = generateChatMessage();
     batch.insert(chatmessage);
     if(count>=1000){
        count=0;
        batch.execute(function(err){
            console.log(err);
            batch = db.collection("chatmessage").initializeOrderedBulkOp();
            console.log("batch execute"+util.inspect(process.memoryUsage()));
            //db.close();
        });
     }
  }
  console.log("execute one chatroom"+util.inspect(process.memoryUsage()));
}
if(count>0){
    batch.execute(function(err){
            console.log(err);
            batch = db.collection("chatmessage").initializeOrderedBulkOp();
        });
}

}

需要使用nodejs.使用Bulk方法将数百万条消息填充到mongo中以进行插入批处理。

但是有一些关于代码的问题

  • 批量执行方法运行async。 当插入数据= 100,000时,没有看到任何批量执行完成,直到所有代码完成执行,可以看到打印“批量执行”。

  • 当messageNum的变量很大时,大约50,000.it将内存不足。

    致命错误:CALL_AND_RETRY_LAST分配失败 - 处理内存不足

变量都是在循环外部定义的,并且运行了batch.execute。 不明白为什么会发生这种情况。

  • 当记录很大时,rss会迅速增加,并且永远不会减少。因为它不是由V8引擎管理的。它会增加直到达到我的计算机的内存大小。

这与DB有关,当我删除DB操作时,没有问题。 我猜batch.execute()方法占用了这个内存。但是即使使用db.close()也无法释放它。

{rss:1449750528,heapTotal:1091999056,heapUsed:922237384}

------------------------------------------- UPDATE1 --- ---------------------------

使用heapdump包获得了多个heapdump snapshoot文件。 enter image description here

根本原因是batch.execute方法是异步调用。直到所有代码都被执行时才会执行,正如我在第一个问题中提到的那样。【也怀疑即使是batch.execute()也是异步执行的。应该运行独立,不受主进程的影响。但我还没有发现它们写入db,并且回调方法中的信息日志尚未打印出来】 因此,所有需要插入mongo的文档都会留在内存中。导致问题。

@joeytwiddle发现你对这个问题有一个共同的看法。 来自bulk-upsert-in-mongodb

没有发现bulk.execute()方法可以配置sync执行。 任何人都有任何想法来解决这个问题。

1 个答案:

答案 0 :(得分:0)

我也遇到了这个错误但是当我使用这个代码时它的工作正常。 简单插入的示例使用Generator和co模块的许多操作。你也可以检查一下;

var MongoClient = require('mongodb').MongoClient,
co = require('co');
test = require('assert');

co(function*() {
 var db = yield MongoClient.connect('mongodb://localhost:27017/test');
 // Get the collection
 var col = db.collection('insert_many_with_generators');
 var r = yield col.insertMany([{a:1}, {a:2}]);
 test.equal(2, r.insertedCount);
 // Finish up test
 db.close();
});