簡體   English   中英

在並發調用涉及讀操作的寫操作的函數時,如何緩解競爭狀況

[英]How to mitigate race condition when concurrently calling a function involving a write operation that depends on a read operation

我有一個名為Ledger的簡單集合,具有以下架構

Ledger: {
  account: String,
  amount: Number // actually an integer
}

我有一個功能可以根據該帳戶上的余額向該帳戶借記:

 const debit = async (account_to_be_debited, amount_to_be_debited) => { let transactions = await Ledger.find({ account: account_to_be_debited }) let balance = transactions.reduce((accumulated_balance, transaction) => { accumulated_balance += transaction.amount return accumulated_balance }, 0) if (balance < amount_to_be_debited) { throw new Error('insufficient funds') } let new_transaction = await Ledger.create({ account: account_to_be_debited, amount: -amount_to_be_debited }) return new_transaction._id } 

現在,我希望能夠在異步環境中執行以下操作:

 // the first debit debit('account_1', 100).then(id => console.log(id)) // another debit debit('account_1', 200).then(id => console.log(id)) 

我擔心的是,如果兩個借記操作同時發生,則存在雙重支出的風險,因為兩個借記操作都將檢查相同的余額。 如果我在執行下一個借記交易之前等待一個借記交易完成,這將不是問題

 let debit_1 = await debit('account_1', 100) let debit_2 = await debit('account_1', 200) 

我知道隨着mongodb 4.0的發布,我可以使用事務,但是我不確定事務是否由mongodb同步執行。 如果是這樣,那么我可以確定每個后續事務都將讀取最近提交的事務反映的更改,並且跨事務的讀取不能同時發生,因為事務不能同時發生。

所以我的問題是:mongodb事務是否適合我的用例,特別是用於緩解上述競爭條件?

如果沒有,我可以采取哪些可能的方法。 我正在用js節點編寫此應用程序,目前正在使用貓鼬對mongodb副本集進行建模和交互。

任何幫助是極大的贊賞。 謝謝。

Mongo事務通常用於確保跨多個集合(或單個集合!)的一組更新/插入全部成功或全部失敗,這聽起來不像您所描述的用例。 相反,您想確保如果有兩個更新,其中一個更新將失敗,這是您應該在數據庫端(而不是應用程序代碼)嘗試並處理的更新。

您可以通過以下方式編寫更新操作:如果更新無效,則更新操作將失敗: db.ledger.updateOne({account: 'account_1', amount: {$gte: 200}}, {$inc: { amount: 200 }})

$gte將確保僅在滿足您條件的文檔上執行此操作,並且您可以查看更新是否成功。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM