用户可以通过发起多个并发提款来同时提款超过其钱包余额

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

我正在更新一个基于

node.js
mongodb
和 ``mongoose`` 构建的财务应用程序,我目前面临着处理从系统中提取资金的逻辑的挑战。问题是,如果用户同时访问资金提取端点,则他们可以请求大于其余额的金额。例如,可用余额为 10 美元,用户可以同时处理多次 10 美元提款。

我知道问题出在哪里,只是我一直无法解决它。我知道发生这种情况是因为这些操作是同时发生的,因此

user.balance
将始终是
10
,因为借方发生在读取之后。我对后端开发比较陌生,所以如果我没有使用正确的术语,请原谅我。这就是我的代码的样子。

 try{
   // Perform tasks such as validating the account number, etc.

   const user = await User.findById(req.user._id);

   if(user.balance < req.body.amount)
     return res.status(400).send({message:"Insufficient Balance"});

    // update the user balance in the DB to user.balance - req.body.amount

    return res.status(200).send({message:"Fund has been sent to the account provided"})
 }

我尝试了一种更新集合中的用户记录并使用该响应来检查用户余额的方法,但我不太确定这是否能完全解决我的问题,或者是否仍然存在漏洞,或者是否有更好的方法处理这个。

这是我尝试的第二种方法

 try{

   // Perform tasks such as validating the account number, etc.
   const idx = uuid()

   const user = await User.findByIdAndUpdate(req.user._id, {withdrawal_intent:idx} {
        new: true,
   });


   if(user.balance < req.body.amount)
     return res.status(400).send({message:"Insufficient Balance"});

    // update the user balance in the DB to user.balance - req.body.amount

    return res.status(200).send({message:"Fund has been sent to the account provided"})
 }

我愿意重构代码以适应处理此问题的最佳方法

P.S:这是一个旧的代码库,所以我可能使用猫鼬的旧语法。

"mongoose": "^5.9.9"

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

首先,我认为您应该在端点上设置速率限制,例如 1 req/s。 其次,如果您尚未在表中定义检查以防止余额为负数,请执行此操作。

我对 MongoDB 不太熟悉,但是 您可以开始可序列化的交易并执行“选择”和“更新”以及“在提款表中插入新记录”。之后,调用 commit。如果您进行了我之前提到的检查,则第二个请求将失败,您应该进行回滚。 出于财务目的,我认为使用程序可能是一个很好的方法。

这是一个例子。

BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;

select "balance", "recordID" into "_balance", "_recordID" 
from "Balance"
where "userID" = "in_userID"
for update;

if ("_balance"< "in_amount") raise exception('INSUFFICENT_BALANCE'); end if;

update "Balance" set "balance" = "balance" - "in_amount" where "recordID" = "_recordID";

insert into "Withdrawal" () values ();

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