gpt4 book ai didi

node.js - Mongodb 和 Nodejs 中的锁

转载 作者:可可西里 更新时间:2023-11-01 09:26:08 29 4
gpt4 key购买 nike

我正在尝试构建一个非常简单的购物应用程序,用户可以在其中使用虚拟货币购买商品。

我为此使用了多个 NodeJS 进程,所以我对异步部分感到害怕。

这是我的做法:

app.post('/buy', function(req, res){

User.findOne({_id: req.userId}, function(err, user){

if(user.balance >= ITEM_PRICE){

User.decrementBalance({_id: req.userId}, function(err){

//Do transaction, give item to user, etc

});

} else {
//Not enough money
}
});
});

这种方法的问题是用户可以在很短的时间内提交多个/buy 请求。这可能会导致竞争条件,即第二个请求在第一个请求减少用户余额之前检查了用户的余额。这会导致用户获得负值并取出比他的余额允许的更多的元素。

有办法解决吗?我正在考虑做一个 User.update() 并验证用户是否被修改。这行得通吗?

最佳答案

您可以使用 Model.findOneAndUpdate()为此,它将在一个原子操作中结合查询余额调整:

User.findOneAndUpdate({
_id : req.userId,
balance : { $gte : ITEM_PRICE }
}, {
$inc : { balance : -ITEM_PRICE } // there is no $dec
}, {
new : true
}, function(err, user) {
...
});

如果查询条件失败(没有用户具有该 ID,或者他们没有足够的余额),user 将为 null(或 未定义,不确定)。由于看起来您只与登录用户打交道,因此该 ID 可能始终有效,因此如果未定义 user 则意味着他们的余额不够高。

由于 new : true,如果返回用户文档,它将反射(reflect) 余额(默认情况下,它将返回旧文档)。

编辑:更多说明:您评估执行 .findOne 和发布更新之间存在竞争条件(这是 User .decrementBalance() 将执行此操作)。

但是,findOneAndUpdate 是特殊的,因为它将使用保证是原子的特定 MongoDB 命令 ( findAndModify ),这意味着查找和更新都将在没有其他操作干扰这些步骤的可能性。

文档摘录:

When modifying a single document, both findAndModify and the update() method atomically update the document.

关于node.js - Mongodb 和 Nodejs 中的锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37619391/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com