[分享]淺談電商庫存模型
阿新 • • 發佈:2019-02-09
本文討論內容不包含秒殺,僅僅是最普遍的庫存模型而已,重點討論如何避免超賣
,少賣
。
1、 基本概念
1.1 超賣
實際庫存已經為0,但是依舊賣出去了。可能導致商家無貨可發。
1.2 少賣
明明有貨,但是庫存被鎖定,導致商家貨賣不出去。
2、 分散式事務簡述
2.1 訊息事務+最終一致性
所謂的訊息事務就是基於訊息中介軟體的兩階段提交,本質上是對訊息中介軟體的一種特殊利用,
它是將本地事務和發訊息放在了一個分散式事務裡,保證要麼本地操作成功成功並且對外發訊息成功,
要麼兩者都失敗,開源的RocketMQ就支援這一特性,具體原理如下:
- 1、A系統向訊息中介軟體傳送一條預備訊息
- 2、訊息中介軟體儲存預備訊息並返回成功
- 3、A執行本地事務
- 4、A傳送提交訊息給訊息中介軟體
通過以上4步完成了一個訊息事務。對於以上的4個步驟,每個步驟都可能產生錯誤,下面一一分析:
- 步驟一出錯,則整個事務失敗,不會執行A的本地操作
- 步驟二出錯,則整個事務失敗,不會執行A的本地操作
- 步驟三出錯,這時候需要回滾預備訊息,怎麼回滾?答案是A系統實現一個訊息中介軟體的回撥介面,訊息中介軟體會去不斷執行回撥介面,檢查A事務執行是否執行成功,如果失敗則回滾預備訊息
- 步驟四出錯,這時候A的本地事務是成功的,那麼訊息中介軟體要回滾A嗎?答案是不需要,其實通過回撥介面,訊息中介軟體能夠檢查到A執行成功了,這時候其實不需要A發提交訊息了,訊息中介軟體可以自己對訊息進行提交,從而完成整個訊息事務
2.2 TCC程式設計模式
所謂的TCC程式設計模式,也是兩階段提交的一個變種。TCC提供了一個程式設計框架,將整個業務邏輯分為三塊:Try、Confirm和Cancel三個操作。
以線上下單為例,Try階段會去扣庫存,Confirm階段則是去更新訂單狀態,如果更新訂單失敗,則進入Cancel階段,會去恢復庫存。
總之,TCC就是通過程式碼人為實現了兩階段提交,不同的業務場景所寫的程式碼都不一樣,複雜度也不一樣,因此,這種模式並不能很好地被複用。
3、 庫存模型
- 1.下單的時候每個訂單都會有預佔庫存。
- 2.訂單出庫或取消解鎖預佔。
- 3.可售庫存 = 現貨庫存 - 預佔庫存
具體下單操作流程是
下單 –> 預佔(預佔庫存+1) –> 支付 –> 出庫(釋放預佔並減庫存,涉及到分散式事務) –> 完成
重點討論此方案的意義,跟出庫部分。
3.1 為什麼設計成預佔庫存?
以下均為個人理解
- 1.庫存和下單分離,下單了不會實際減少庫存。真正的實物庫存跟邏輯庫存分離,方便(盤庫、補貨等)
僅僅用實物庫存
的場景跟高併發
的場景(下單)分離。 - 2.預佔可以減少庫存表的操作頻率,減庫存可以在發貨的時候統一處理。(操作多次預佔表後僅在必要時操作一次庫存表,跟1有共通之處)
3.2 預佔庫存怎麼加?
- 1.可以用mysql樂觀鎖(version遞增避免aba)
- 2.可以用redis watch(同樣基於cas,無aba)
3.3 出庫部分怎麼保證事務?
1.先出庫還是先釋放預佔?
為了避免超賣選擇先減庫存,再釋放預佔。
2.如何保證事務一致性?
採用訊息機制的2pc保證分散式事務。