优化异步查询 nodeJs

pse*_*pse 5 optimization mongodb node.js async-await

我正在开发一个拥有超过 25k 个用户的项目,每次为 创build 任何记录时Oppurtinity module,它都会执行此函数,该函数在 mongodb 中为每个用户插入通知详细信息,问题是它用完了 cpu 并且不让任何其他 API 来产生结果,直到这个异步结束它会占用时间,同时服务器不加载任何其他数据/它给出延迟响应。

  1. 节点- v10.15.3
  2. MongoDB 外壳版本 v4.0.17
  3. 服务器=Windows=Memory-8GB
  4. 中央处理器 2.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)

Ric*_*unn 6

您的示例代码和您的问题存在一些问题。我不得不假设您正在使用这些库:AsyncMongoDB。请尝试更好地组织您的问题。

如果我假设正确,那么您没有仔细遵循文档,因为您没有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查询。

  • 我正在研究这个,并将更新为我醒来的内容,非常感谢:D (2认同)
  • 30k *用户*没有任何意义。您需要掌握每秒处理的请求数量,尤其是在高峰时段。然后您需要考虑大多数请求正在做什么(它是一个长时间运行的任务吗?它会消耗很多内存吗?)。如果您的服务器与大多数其他 API 服务器一样,那么它实际上只是数据库的包装器。如果是这样,数据库将是您的第一个瓶颈。想想如何提高Mongo效率,网上有很多文章。对于诸如通知之类的内容,您应该考虑将 Redis 等内存存储与 Mongo 一起使用。 (2认同)