如何防止mongodb支持的分布式nodejs Web服务器体系结构中的竞争条件

时间:2013-08-24 04:55:15

标签: node.js mongodb express mongoose distributed

以下是对我的问题的描述:

  1. 我在负载平衡器后面的nodejs(express.js)中编写了x个web工作者。这些工作人员将数据写入mongodb(mongoose.js)
  2. 我设置了端点y,以便在处理程序的中间件链中的某个点上,我正在执行以下逻辑:如果请求用户存在于数据库中,则获取它,更新一些字段然后将其存储回来。如果它不存在,请将其插入mongo。
  3. 请注意!我无法使用Mongoose的findAndUpdateOne() - 这将是原子的 - 由于域特定的逻辑,即。如果用户已经存在,则使用某个值更新它,否则将其插入另一个值。

    1. 问题是,同一个用户(数据库中尚不存在)的两个请求经常会遇到两个不同的工作者。当用户处理中间件时,两个工作人员将确定该用户不存在并尝试插入它然后更新它。当然这会导致错误,例如。验证错误:我为每个用户验证和其他人设置了一个唯一的电子邮件。
    2. 我该如何防止这种情况?

1 个答案:

答案 0 :(得分:2)

您可以使用$set$setOnInsert更新运算符来实现此目的。

来自MongoDB $setOnInsert docs

  

如果使用upsert:true的更新操作导致插入a   然后$ setOnInsert将指定的值分配给字段   在文件中。如果更新操作没有导致插入,   $ setOnInsert什么都不做。

  

如果带有upsert:true的db.collection.update()找到了匹配的文档,那么MongoDB会执行更新,应用$ set操作但忽略$ setOnInsert操作。

所以,这应该可以解决问题:

var now = Date.now();

Users.update({ _id: 1 }, {
  $set:         { updatedAt: now },
  $setOnInsert: { createdAt: now }
}, {upsert: true}, function(err, doc) {

  // resultant doc is available here

})