在预订系统中,只有5个不同的用户可以创建预订。如果 100 个用户同时调用预订 api,如何使用锁定处理并发。我正在使用nodejs和mongodb。我浏览了 mongo 并发文章和 mongodb 中的事务,但找不到任何带有锁定的示例编码解决方案。
我已经通过乐观并发控制实现了解决方案(当资源争用较低时 - 这可以使用 versionNumber 或 timeStamp 字段轻松实现)。
提前感谢您向我建议锁定解决方案。
现在的算法是:
第 1 步:从 userSettings 集合中获取 userAllowedNumber。
//Query
db.getCollection('userSettings').find({})
//Response Data
{ "userAllowedNumber": 5 }
第2步,从预订集合中获取当前的bookedCount。
//Query
db.getCollection('bookings').count({ })
//Response Data
2
第3步,如果
bookedCount <= userAllowedNumber
则插入预订。
//Query
db.getCollection('bookings').create({ user_id: "usr_1" })
我在mongodb社区深入讨论了事务加锁的问题。在结论中,我了解到并发现了交易的局限性。我们没有可以使用锁来处理此任务的并发请求。
您可以在此链接查看完整的 Mongodb 社区对话 https://www.mongodb.com/community/forums/t/implementing-locking-in-transaction-for-read-and-write/127845
使用 Jmeter 测试的 Github 演示代码显示了限制,无法处理此任务的并发请求。 https://github.com/naisargparmar/concurrencyMongo
新的建议仍然欢迎和赞赏
对于事务的简单示例,首先您需要有一个客户端连接到 MongoDB。
const client = new MongoClient(uri);
await client.connect();
一旦拥有客户端,您就可以创建一个可以进行交易的会话:
const session = await client.startSession();
const transactionResults = await session.withTransaction( async () => {
await client.db().collection("example").insertOne(example);
}, transactionOptions);
随着
transactionOptions
是:
const transactionOptions = {
readPreference: 'primary',
readConcern: { level: 'majority' },
writeConcern: { w: 'majority' }
};
在 MongoDb 文档中查找有关读/写问题的信息。 根据您的用例,您还可以考虑
findAndModify
在更改时锁定文档。
为了解决您的问题,您还可以尝试使用Redlock(https://redis.com/redis-best-practices/communication-patterns/redlock/)进行分布式锁定或使用互斥锁进行实例锁定。
另一种方法是自己编写或导入 https://github.com/Zurili/mongo-distributed-locks with
npm i mongo-distributed-locks
然后使用项目中的示例来包装您的代码:
import DLocks from 'mongo-distributed-locks'
async function createBooking(userId) {
const lock = await DLocks.lock({
resource: 'bookings',
id: userId
})
try {
await createBooking( userId )
}
finally {
await DLocks.unlock(lock)
}
}