扣庫存流程


1,同步扣庫存

在訂單生成的時候就扣去庫存,存在一些問題:

  • 會造成訂單被取消,實際庫存扣了,但是沒有支付,也就造成了少買的情況
  • 即時扣庫存,並發性太差

2,異步扣庫存

對於電商網站,比如某東,會在訂單支付成功后,有一個出庫的過程,有可能出庫成功,也有可能出庫失敗。

庫存有兩部分:一個緩存Redis層, 一個數據庫MySQL層

2.1當客服新增了5個庫存,那么,緩存Redis和數據庫MySQL層都需要增加5個庫存,這個使用分布式事務的最終一致性來滿足要么全家,要么全部不加。

2.2在訂單生成的時候,需要先扣庫存,先扣除Redis,生成支付訂單,這時不扣除MySQL的庫存

2.3當Redis庫存扣完了,就無法下單了,下單失敗,在外層把請求擋住

2.4用戶支付訂單,訂單支付成功后,返回我的訂單,有一個出庫過程

2.5出庫是一個MQ異步解耦的消息隊列,這個過程是扣除MySQL庫存,如果扣除成功,那么出庫成功,完成訂單的整個流程,進入發貨狀態;如果扣除庫存失敗,則進行一些列操作1)訂單狀態改成取消2)返還Redis庫存3)退款

 

3,Redis庫存和MySQL庫存

支付前是預扣,扣除Redis庫存

支付后是真正扣除,扣MySQL庫存

在一些極端情況下數據不一致

3.1如果Redis庫存和MySQL庫存一直,沒問題

3.2如果Redis庫存比MySQL庫存多,超賣的訂單出庫失敗

3.3如果Redis庫存比MySQL庫存少,少買,有貨沒賣出去

這樣總體不會出問題,MySQL數據庫層,保證庫存不會再真正有問題

 

4,如何檢測Redis和MySQL庫存不一致

4.1暴力方法,很容易想到,找一個低峰期,比如凌晨2點,周期性強行覆蓋,但是也可能在這個時候出現一個訂單,出庫的過程中,扣除了MySQL庫存,但是沒有扣除Redis庫存(我是這樣理解的:這時有一個訂單,通過Redis的庫存扣除后,然后支付進入出庫狀態,這時已經取出MySQL的庫存數要同步到Redis中,緊接着MySQL庫存扣除了,Redis的數據還是扣除前的數據,所以就會數據不一致)

這個就是數據庫同步緩存的更新機制方面的問題

屬於一致性的邏輯設計的問題

緩存數=數據庫庫存數-待扣數

當然這里面也還有其它的方案,以及考慮到一致性的要求高低,可以使用簡單或復雜的方案 就看系統復雜度了,越是大系統就要拆得越細

比如待扣數又可以放到一個隊列里面,或者緩存里面,同時有計數,直接讀計數就行

比如放到mongo,已支付待出庫的數量,一般也不會很大,count一下,也不會損失多少

所以一般系統都不能完全保障數據鏈不出錯,但一定要有補償,就是出錯了可以糾錯 要保障不出錯的代價顯然太大

同步是有一套刷新機制,可以定時,也可以通過MQ,或者監控不一至同步等等。。。 也叫做保障緩存數據的新鮮度

一般不會太長時間,半小時,幾分鍾都有可能,不同場景需求不一樣

 

 

5.買火車票的12306,晚上的時間都不能買票,這個時間估計是在同步庫存,將數據庫庫存同步到redis庫存中, 但是買火車票之類,在訂單生成前,必須扣除實際庫存,也就是要扣除mysql的庫存,

因為買火車票和購物不一樣,購物可以付款后出庫,但是買票這種,支付前就必須出庫,因此,要將出庫過程提前, 只有出庫成功,才能生成訂單,同樣要引入redis庫存

5.1先扣緩存中的庫存,扣除成功后,然后才可以去扣mysql中的庫存

5.2如果扣除緩存中的庫存失敗,就會擋在外面,返回庫存不足,這些請求不會穿刺到mysql中,擋住了大多數的請求壓力。

5.3redis庫存會和mysql庫存不一致,極端情況下是肯定有的,需要進行庫存同步

5.3.1當緩存庫存比數據庫庫存多,那么就會出現,查詢有票,但是就無法下單,下單的時候就說庫存不足, 這樣也不會超賣,當redis的庫存多的那部分扣完了,就可以把請求全部當在外面了。 對於12306,有時候,查詢的時候有票,但是下單的時候返回庫存不足,然后重新查詢發現還是有庫存, 這種情況應該就是redis中庫存和mysql中庫存不一致造成的。

5.3.2當緩存庫存比數據庫緩存少,那么不會出問題,只會出現有票,但是沒有出售的情況,等完成庫存同步一下, 明天又准確了。

5.3.3當然,mysql扣除庫存的部分,還需要在前面加入隊列緩沖,避免請求過多,讓應用程序或數據庫崩潰。

 

本文參考:https://my.oschina.net/134596/blog/3129705


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM