1、在設計公司的庫存架構的時候,出現了問題,當處理無座商品的時候,發現,復原邏輯有問題,具體的邏輯為:
比如如果庫存設定為1 ,則
(1) 使用者1 下單成功,庫存-1
(2)使用者2下單因為庫存 是0是以 下單失敗,開始復原,復原的時候+1,導緻目前的庫存為 1(實際上這個庫存已經被使用者1買走了)
(3)使用者3 下單成功 ,庫存-1
最後:導緻庫存1 賣了2次,
原因分析:
復原邏輯沒有顯示訂單号,應該嚴格按照訂單号復原,否則會把别人的庫存復原掉;
大麥的邏輯設定:
首先第一步:
假設庫存總量為total_count,本次使用者下單的數量為10;
資料庫有3列,總 total_count,已售: sale_count,剩餘 marging_count;
這些都放在一個事務中
try{
1、查詢訂單庫存,如果庫存不足直接傳回 查詢的條件唯一(比如按照訂單号)
2、将庫存鎖定比如 1是未鎖定,2是鎖定 則 設定目前的行為鎖定狀态;
update recrod set status=2 where status=1 and 條件;
3、如果需要修改的庫存有多條,對需要修改的庫存進行排序(防止死鎖)
4、逐行設定庫存:
update sale_count+10 ,margin_count-10 where 條件+status=2 and sale_count-10>=0;
} catch(Exception e){
}
之是以如此設定:
1、全部放在一個事務中,友善異常復原,
2、使用一個status鎖定狀态,因為mysql是行鎖,保證事務并發處理的時候隻有個線程可以往後走,後面的線程會等待,處理一條資料,
3、指定一個唯一條件,比如按照訂單号復原,如果訂單号不滿足直接退出,防止復原别人的庫存
4、設定庫存的時候,需要先進行排序,讓線程順序執行,防止死鎖,舉個栗子:
如果不排序:A,B兩個線程 ,復原庫存 ,如果第一個A線程扣減了X1行,下一步執行Y1行,
但另一個線程B,扣減了Y1,下一步需要扣減X1行,這時候,
A線程占着X1行,需要等待B線程釋放Y1行,
而同時B線程占着Y1行,等待着A線程釋放X1行,

産生了死鎖
是以必須要排序;
5、扣減的時候執行 條件添加:sale_count-10>=0; 保證即使某個地方有問題,也不會扣減為負數;
問題:1、sale_count-10>=0; 不是小于=0;
是的;
2、排序如何排序,根據什麼條件排序 根據票品的ID進行排序,保證順序;
3、我們的設定狀态是鎖定狀态?那也就是每個庫存都要設定一個是否鎖定的狀态? 還是專門設計一張表,鎖定狀态,賣座的優惠券發券如何設計
可以加一張新表把狀态放進來;