淺析扣減庫存的方案設計

你好,我是悟空,今天來探討下扣減庫存的方案。redis

生活中,咱們老是用各類電商app搶購商品,可是庫存數是不多的,特別是秒殺場景,商品可能就一件,那如何保證不會出現超賣的狀況呢?數據庫

1、扣減庫存的三種方案

(1)下單減庫存

用戶下單時減庫存緩存

優勢:實時減庫存,避免付款時因庫存不足減庫存的問題併發

缺點:惡意買家大量下單,將庫存用完,可是不付款,真正想買的人買不到app

(2)付款減庫存

下單頁面顯示最新的庫存,下單時不會當即減庫存,而是等到支付時纔會減庫存。高併發

優勢:防止惡意買家大量下單用光庫存,避免下單減庫存的缺點spa

缺點:下單頁面顯示的庫存數可能不是最新的庫存數,而庫存數用完後,下單頁面的庫存數沒有刷新,出現下單數超過庫存數,若支付的訂單數超過庫存數,則會出現支付失敗。.net

(3)預扣庫存

下單頁面顯示最新的庫存,下單後保留這個庫存一段時間(好比10分鐘),超過保留時間後,庫存釋放。若保留時間事後再支付,若是沒有庫存,則支付失敗。線程

優勢:結合下單減庫存的優勢,實時減庫存,且緩解惡意買家大量下單的問題,保留時間內未支付,則釋放庫存。3d

缺點:保留時間內,惡意買家大量下單將庫存用完。併發量很高的時候,依然會出現下單數超過庫存數。

2、如何解決惡意買家下單的問題

這裏的惡意買家指短期內大量下單,將庫存用完的買家。

(1)限制用戶下單數量

優勢:限制惡意買家下單

缺點:用戶想要多買幾件,被限制了,會下降銷售量

(2)標識惡意買家

優勢:賣家設定一個備用庫存,當支付時,庫存已用完,扣減備用庫存數,這就是常見的補貨場景

缺點:因高併發場景下,數據可能存在不一致性的問題

3、如何解決下單成功而支付失敗(庫存不足)的問題

(1)備用庫存

商品庫存用完後,若是還有用戶支付,直接扣減備用庫存。

優勢:緩解部分用戶支付失敗的問題

缺點:備用庫存只能緩解問題,不能從根本上解決問題。另外備用庫存針對普通商品能夠,針對特殊商品這種庫存少的,備用庫存量也不會很大,仍是會出現大量用戶下單成功卻因庫存不

足而支付失敗的問題。

4、如何解決高併發下庫存超賣的場景

庫存超賣最簡單的解釋就是多成交了訂單而發不了貨。

場景:

用戶A和B成功下單,在支付時扣減庫存,當前庫存數爲10。因A和B查詢庫存時,都還有庫存數,因此A和B均可以付款。

A和B同時支付,A和B支付完成後,能夠看作兩個請求回調後臺系統扣減庫存,有兩個線程處理請求,兩個線程查詢出來的庫存數 inventory=10,

而後A線程更新最終庫存數 lastInventory=inventory - 1 = 9,

B線程更新庫存數 lastInventory=inventory - 1 = 9。

而實際最終的庫存應是8纔對,這樣就出現庫存超賣的狀況,而發不出貨。

那如何解決庫存超賣的狀況呢?

1.SQL語句直接更新庫存,而不是先查詢出來,而後賦值

     UPDATE [庫存表] SET 庫存數 - 1

2.SQL語句更新庫存時,若是扣減庫存後,庫存數爲負數,直接拋異常,利用事務的原子性進行自動回滾。

3.利用SQL語句更新庫存,防止庫存爲負數

     UPDATE [庫存表] SET 庫存數 - 1 WHERE 庫存數 - 1 > 0

若是影響條數大於1,則表示扣減庫存成功,不然不更新庫存,並退款。

5、秒殺場景下如何扣減庫存

(1)下單減庫存

因秒殺場景下,大部分用戶都是想直接購買商品的,能夠直接用下單減庫存。

大量用戶和惡意用戶都是同時進行的,區別是正經常使用戶會直接購買商品,惡意用戶雖然在競爭搶購的名額,可是獲取到的資格和普通用戶同樣,因此下單減庫存在秒殺場景下,惡意用戶下單並不能形成以前說的缺點。

並且下單直接扣減庫存,這個方案更簡單,在第一步就扣減庫存了。

(2)將庫存放到redis緩存中

查詢緩存要比查詢數據庫快,因此將庫存數放在緩存中,直接在緩存中扣減庫存。

(3)使用量自增方式

能夠先增長已使用量,而後與設定的庫存進行比較,若是超出,則將使用量減回去。

另外其實真實的項目中,用到了更多的機制來保證可以正常扣減庫存,本篇是拋磚引入,但願你們提出寶貴的建議和方案~。

本文同步分享在 博客「7年一線互聯網經驗,超愛圖解底層原理,全棧一枚」(CNBlog)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索