1,超賣問題的話,我們一般是通過事務來解決,sql語句中直接將更新和查詢放在一起,通過行鎖
startTransaction();
try{
int remainder = statement.query("select remainder from stock where stock_id='$STOCK_ID$'"; 得到此刻庫存
然后根據訂單要求數量來進行比較,如果庫存大於等於訂單要求數量,就執行減坤村操作
}catch(Exception e){rollback();}
commit(); 這個時候就出現超賣問題了,因為上面三個用戶同時搶購的時候,進入這個事務,然后同時執行update操作,
行鎖這個時候排他性,會將update操作串行化,所以最后就發生了超賣 就是上面是兩步操作,所以不可以
2,簡單的是將上面兩句語句合並為一句 update stock set remainder=remainder-amount where stock_id='$STOCK_ID$' and $remainder>=$amount 這樣就可以了
3,但是高並發下的情況又不一樣了 因為太多的update 都需要等待鎖,大量的請求超時
通過redis來減庫存
a,監聽相關物品的庫存信息,事務開啟前保證物品庫存不被修改
b,獲取現有庫存信息,判斷滿足條件
c,如果滿足就進行扣除操作
d,如果第一步有人更新了物品庫存信息,進行重試
e,如果庫存為0或者剩余庫存不滿足當前訂單扣除數量就退出。
秒殺服務的實際操作版本:
用戶秒殺請求到達api網關,先到redis(沒有了就做一個標記)中判斷秒殺的商品是否庫存售罄,如果售罄直接返回秒殺失敗
基於令牌桶算法的rateLimiter進行限流,得到令牌的請求才可以繼續進入到下面的邏輯
要調用下游秒殺服務的接口,因為網關的並發處理能力大於下游的秒殺服務的處理能力,所以要通過排隊來限制涌入下游系統的流量,
進入秒殺服務后,要考慮到分布式事務的問題,因為秒殺服務扣減庫存,然后訂單生成訂單和郵寄的相關信息,要保證信息的一致性,采用MQ,可靠消息最終一致性方案 MQ事務消息來實現。
mq發送方在秒殺服務中,本地事務執行成功以后,也就是扣減秒殺庫存成功以后,就可以返回秒殺下單成功了