我有一个CSV文件,我正在以流的形式阅读,并使用转换转换为JSON,然后将每行异步存储到数据库。
问题是从文件读取速度很快,因此会导致非常大量的并发异步数据库操作,导致应用程序停止运行。
我想限制应用程序,以便在任何给定时间内最多有N个未完成的数据库操作正在进行中。
这是我的_transform函数的基本核心:
parser._transform = function(data, encoding, done) {
//push data rows
var tick = this._parseRow(data);
//Store tick
db.set(tick.date, tick, function(err, result) {
console.log(result);
if(err) throw err;
});
this.push(tick);
done();
};
我看了几个选项,但这些似乎是最好的候选人:
这是我对'并发限制解决方案'的初步尝试:
var limit = 100;
var running = 0;
parser._transform = function(data, encoding, done) {
//push data rows
var tick = this._parseRow(data);
this.push(tick);
//Store tick to db
if (running < limit) {
console.log("limit not reached, scheduling set");
running++;
cb.set(tick.date, tick, function(err, result) {
running--;
console.log("running is:" + running);
console.log(result);
if(err) throw err;
});
} else {
console.log("max limit reached, sleeping");
setTimeout(this._transform(data, encoding, done),1000);
}
done();
};
本周我才开始使用node.js,所以我不清楚解决这个问题的正确模型是什么。
注意:我知道的一些事情是,如果使用后一种模式,至少应该是指数退避,并且应该有一些“最大退避”系统,所以不要吹掉掉话堆。尽管如此,试图在这里保持简单。
答案 0 :(得分:2)
并发限制解决方案选项是我要采用的方法,但我不是自己实现,而是使用async模块。具体来说,是queue方法。
类似的东西:
var dbQueue = async.queue(function(tick, callback) {
db.set(tick.date, tick, function(err, result) {
console.log(result);
callback(err, result);
});
}, 3); // the last arg (3) is the concurrency level; tweak as needed
parser._transform = function(data, encoding, done) {
//push data rows
var tick = this._parseRow(data);
dbQueue.push(tick);
this.push(tick);
done();
};
这会将您的数据库操作限制为3次。此外,您可以将队列的saturated
和empty
事件用于您的信息流pause
/ resume
,以便在资源使用方面更加有限(如果您正在阅读非常大的文件,那将会很棒。这看起来像是:
dbQueue.saturated = function() {
parser.pause();
}
dbQueue.empty = function() {
parser.resume();
}
答案 1 :(得分:1)
数据库限于在任何给定时间同时进行一次磁盘写入。考虑到这一点,任何并行写入都会降低整个操作的速度。 如果文件足够小,请尝试将其全部读入内存,然后在一次操作中将其写入数据库。否则将其拆分为大块,然后一个接一个地查询它们。