我们有一个 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 本身 - 例如,一些锁定机制。
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');
}
让我知道它是否有效:)