高併發,業務量大的業務場景下,資料庫減庫存的解決方案
1,使用者下單購買商品的情況下,如果有多個人同時下單,減除庫存的情況下,如果遇到了減去庫存的併發問題,這個時候應該怎麼處理呢?
傳統的業務流程場景下,處理流程是這樣的: 1,庫存查詢,通過dao查詢商品庫存,返回庫存數量 select gnum from goods where gid=#{gid} 2,判斷庫存是否充足,充足進行庫存減扣 update goods set gnum=gnum-#{num} where gid=#{gid}但是在減去庫存的時候往往會出現一些意想不到的錯誤,出錯後程序設計可能會有“重試”機制,但是在重試時,可能會得到錯誤的資料,導致重複減扣或者庫存為負數。
重試導致錯誤的根本原因
這樣雖然避免了程式出錯,“重試”機制的減扣沒有導致資料出現錯誤,但是如果使用者發生了併發的購買動作(秒殺類業務特別容易出現),流程如下:
其根本原因是,設定操作發生的時候,沒有檢查實際庫存與查詢出來的庫存有沒有變化,理論上: 庫存為5時,使用者A的庫存設定才能成功 庫存為5時,使用者B的庫存設定才能成功
實際執行的時候: 庫存為5,使用者A的set goods=2確實應該成功 庫存變為2了,使用者B的set goods=3應該失敗掉
所以,在資料量較大的情況下,減庫存應該是以下這種方案: update goods set gnum=#{new_num} where gid=#{gid} 修改為: update goods set gnum=#{new_num} where gid=#{gid} and gnum=#{old_num} 這樣修改後,使用者A設定庫存為2了,使用者B再去設定庫存,通過條件gnum=#{old_num}判斷條件已經不滿足了,從而保證了資料的一致性。
總結: 在業務複雜,資料量大,併發量大的情況下,庫存扣減容易引發資料的不一致,常見的優化方案有兩個:
- 呼叫“設定庫存”介面,能夠保證資料的冪等性
- 在實現“設定庫存”介面時,需要加上原有庫存的比較,才允許設定成功,能解決高併發下庫存扣減的一致性問題