从两个不同的源更新相同的 MongoDB 文档,同时避免竞争条件

问题描述 投票:0回答:1

我们有一个 MongoDB 集合,我们称之为

Accounts
。每个帐户都保存一个
devices
数组。

const accountSchema = new mongoose.Schema(
  {
     ...
     devices: [devicesSchema],
     ...
  }
);

const devicesSchema: Schema = new mongoose.Schema(
  {
    deviceId: String,
    platform: String,
    ...
  },
  { _id: false, toJSON: { virtuals: true }, toObject: { virtuals: true } }
);

我们有一个 webhook,用于接收更新这组设备的帐户事件。例如,在快乐路径情况下,Webhook 事件执行以下代码:

const existingDevices = account.devices;
const newDevices = existingDevices.filter(...).map(...).concat(...) // do stuff to the existingDevices array

await Account.findOneAndUpdate(
  { _id: account._id },
  {
    devices: newDevices
  }
);

这个效果很好。但是,当收到同一帐户的两个 Webhook 时,我们面临两个 Webhook 尝试更新同一数组的危险,从而导致仅完成两个更新之一的竞争条件。

有没有 MongoDB 的方法来解决这个问题?我熟悉其他方法,例如将事件从 Webhook 传递到按顺序处理事件的队列,或者按顺序将事件发送到我们的 Webhook 的 Webhook 网关,但我特别想知道是否有任何有效的方法可以做到这一点MongoDB 本身 - 例如,一些锁定机制。

node.js mongodb webhooks race-condition
1个回答
0
投票

mongoDB 确实提供乐观并发。 这是一个类似的问题 - https://www.mongodb.com/community/forums/t/does-mongodb-transactions-implement-optimistic-concurrency-locking-by-default/234943

你可以这样做,它可能会有所帮助,但我担心如果争用非常高,那么它可能会再次发生冲突。

const res=await Account.findOneAndUpdate(
  { _id: account._id, __v: account.__v },  // __v is the version field
  {
    devices: newDevices,
    $inc: { __v: 1 }  // Increment the version field
  }
);
if (!res) { 
  console.log('Update conflict: Document version mismatch');
}

让我知道它是否有效:)

© www.soinside.com 2019 - 2024. All rights reserved.