1. 程式人生 > >[分享]淺談電商庫存模型

[分享]淺談電商庫存模型

本文討論內容不包含秒殺,僅僅是最普遍的庫存模型而已,重點討論如何避免超賣少賣

1、 基本概念

1.1 超賣

實際庫存已經為0,但是依舊賣出去了。可能導致商家無貨可發。

1.2 少賣

明明有貨,但是庫存被鎖定,導致商家貨賣不出去。

2、 分散式事務簡述

2.1 訊息事務+最終一致性

所謂的訊息事務就是基於訊息中介軟體的兩階段提交,本質上是對訊息中介軟體的一種特殊利用,
它是將本地事務和發訊息放在了一個分散式事務裡,保證要麼本地操作成功成功並且對外發訊息成功,
要麼兩者都失敗,開源的RocketMQ就支援這一特性,具體原理如下:

圖 fenzu

  • 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保證分散式事務。