詭異的 庫存重複扣減 問題

2021-10-09 20:29:18 字數 1227 閱讀 7002

業務場景:庫存扣減場景,消費方呼叫dubbo服務,扣減訂單的庫存

dubbo配置:5s超時時間,未配置預設重試次數

消費方:對商品加redis分布式鎖,防止併發扣減,失效與超時時間為10s

問題:使用者對相同商品的訂單,同時發起扣減庫存請求,造成了未扣減,或同一訂單多扣減的情況

疑惑:未扣減可能是失敗了,但為什麼會同一訂單多扣減?明明加了redis鎖啊!

但問題,就出在redis鎖上

1.大量相同商品扣減請求發出

2.消費方對一筆訂單a的商品加鎖,其他訂單請求進來後redis等待

4.當訂單量巨大,必然會造成訂單b的redis等待超時(10s),此時dubbo請求超時(5s)

5.另一方面,由於當前大量執行緒不斷進入並持續等待,造成cpu遲緩,當前訂單a庫存的操作時間變長,便可能造成扣減庫存變長(7s),訂單adubbo請求超時(5s),而此時訂單a仍在扣減庫存

6.訂單b重試2次,均未搶到鎖,扣減失敗

7.訂單a扣減1次後,由於重試,再次扣減1次,甚至2次

經過情景復現,可以知道,由於

1.dubbo的預設重試機制

2.redis鎖的等待超時

最終造成了這種情況,如何避免呢?

dubbo:

1.對非冪等性介面,dubbo不進行重試

2.對於庫存扣減這種操作,消費方不關心操作結果,操作成敗與否的重任交給服務方,所以dubbo請求超時時間可以定位100ms甚至更低

消費方:

1.服務方介面新增冪等性校驗:如通過redis鎖對訂單號加為期10s的鎖(時間可結合業務),盡量防止重複請求與併發

2.引入失敗重試機制,對redis超時或扣減失敗的訂單資料進行記錄,利用定時任務等機制重試1-2次。提高系統的容錯性與效能

上面的復現中,我們提到了可能的重複扣減的可能性場景,但結合我所遇到的問題,依然遺留下兩個問題:

1.dubbo預設重試機制是2次,加上第一次的請求,一共是3次,但我看到共有4次該訂單的請求,十分不解!

2.在【復現】中模擬的重複扣減場景裡,按理重複的扣減應該是間隔1-5s左右的時間間隔,但重複的扣減記錄卻是相同的扣減時間,難道在redis鎖下,併發了?不解...

如果有大佬看到此處,麻煩提出您的意見和建議,感謝?....

關於庫存扣減問題

昨天面試的時候,被面試官問到庫存扣減問題。估計面試官把我的專案當成秒殺了。怪我自己沒介紹清楚專案,自己挖坑。今天在部落格上看了一些關於庫存扣減問題,主要還是覺得比較合適的方式就是使用redis分布式鎖,這是最簡單的方案,但是如果事務過大,會有效能問題.操作不當,會有死鎖問題 如果兩個執行緒同時執行的...

關於電商庫存扣減問題

b2c 庫存扣減方式 1 直接扣減實際庫存 直接採用實際庫存,每次客戶下單扣減實際庫存,容易導致庫存占用,對銷售和運營都不合理。a 如果購買使用者未付款,實際庫存導致庫存被扣減,讓有意願購買的使用者無從下單,對銷售業務有很大影響 b 未付款訂單給予30 40 鐘付款等待時間,未付款自動釋放虛擬銷售庫...

高併發下的庫存扣減方案

那年還很low db 剛開始我們的營銷專案組身單力薄,人微言輕 那時營銷業務才剛開始發展,此時我們把業務放到第一位,技術方案為滿足時間內業務發展所讓步。大家應該可以猜到,這個時候我們很low的庫存扣減方案 直接上資料庫。根據業務訴求,每個活動會儲存乙份實時變化的庫存,參與活動時,實時扣減資料庫,操作...