[英]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.