pse*_*pse 5 optimization mongodb node.js async-await
我正在开发一个拥有超过 25k 个用户的项目,每次为 创build 任何记录时Oppurtinity module,它都会执行此函数,该函数在 mongodb 中为每个用户插入通知详细信息,问题是它用完了 cpu 并且不让任何其他 API 来产生结果,直到这个异步结束它会占用时间,同时服务器不加载任何其他数据/它给出延迟响应。
v10.15.3v4.0.17Memory-8GB2.70GHz speed我想知道,这里有什么问题,是代码吗,如果是,我该如何优化它?
async.eachSeries(users, (eachuser, next) => {
db.notifications.find({user_id:eachuser._id},function(errr,opp_noti){
if(opp_noti.length != 0){
db.notifications.update( { user_id:eachuser._id},{$push:{oppurtunity:oppurtunity_id}},function(errr,result){
})
}else{
db.notifications.insert({user_id:eachuser._id,oppurtunity:[oppurtunity_id]},function(errr,result){
})
}
})
next();
})
Run Code Online (Sandbox Code Playgroud)
您的示例代码和您的问题存在一些问题。我不得不假设您正在使用这些库:Async和MongoDB。请尝试更好地组织您的问题。
如果我假设正确,那么您没有仔细遵循文档,因为您没有async.eachSeries正确实现该函数 -eachSeries期望async函数作为第二个参数。
我已经根据这两个库的文档重写了您的代码。我以前从未使用过它们,但我有理由相信它是正确的。
async.eachSeries(users, async (user) => {
const user_id = user._id;
const cursor = db.notifications.find({ user_id });
const count = await cursor.count();
if (count > 0) {
return db.notifications.update({ user_id },
{
$push: { oppurtunity: oppurtunity_id } // where is oppurtunity_id defined?
}
)
} else {
return db.notifications.insert({
user_id,
oppurtunity: [oppurtunity_id]
})
}
})
Run Code Online (Sandbox Code Playgroud)
您可能已经意识到这一点,但async.eachSeries会通过串联运行请求来限制请求。虽然出于各种原因这可能是必要的,但它会减慢进程并且不会利用 Node 的非阻塞特性。async.each将并行运行它们,理论上这是最快的,但在 25K 记录时可能会导致问题。因此,我建议您采取中间立场并考虑使用async.eachOfLimit,设置并行限制并查看其性能。
您还可以通过不为每个用户查询数据库来进一步分解问题并获得显着的性能提升。尝试在一个查询中提前获取所有需要更新的用户。
类似下面的内容将notifications在一个查询中返回集合中的所有 ID (可能不止一个,但仍然比n好得多)。
const user_ids = db.notifications.find({}, { _id:1 }).map(item => item._id)
Run Code Online (Sandbox Code Playgroud)
一旦您拥有存在的 ID,您就可以创建两个工作负载,一个用于运行所有db.notifications.update查询,另一个用于运行所有db.notifications.insert查询。