架構之旅1 - 扣減庫存


生活中,我們總是用各種電商app搶購商品,但是庫存數是很少的,特別是秒殺場景,商品可能就一件,那如何保證不會出現超賣的情況呢?

一、扣減庫存的三種方案

(1)下單減庫存

  用戶下單時減庫存

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

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

(2)付款減庫存

  下單頁面顯示最新的庫存,下單時不會立即減庫存,而是等到支付時才會減庫存。

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

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

(3)預扣庫存

  下單頁面顯示最新的庫存,下單后保留這個庫存一段時間(比如10分鍾),超過保留時間后,庫存釋放。若保留時間過后再支付,如果沒有庫存,則支付失敗。

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

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

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

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

(1)限制用戶下單數量

  優點:限制惡意買家下單

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

(2)標識惡意買家

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

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

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

(1)備用庫存

  商品庫存用完后,如果還有用戶支付,直接扣減備用庫存。

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

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

足而支付失敗的問題。

四、如何解決高並發下庫存超賣的場景

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

場景:

用戶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語句更新庫存時,如果扣減庫存后,庫存數為負數,直接拋異常,利用事務的原子性進行自動回滾。

     參考之前我寫的博客:30分鍾全面解析-SQL事務+隔離級別+阻塞+死鎖

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

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

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

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

(1)下單減庫存

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

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

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

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

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

(3)使用量自增方式

可以先增加已使用量,然后與設定的庫存進行比較,如果超出,則將使用量減回去。

 

項目中用到了很多機制,但是沒有總結出來,學習架構需要不斷地總結。


作  者: Jackson0714
出  處:http://www.cnblogs.com/jackson0714/
關於作者:專注於微軟平台的項目開發。如有問題或建議,請多多賜教!
版權聲明:本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。
特此聲明:所有評論和私信都會在第一時間回復。也歡迎園子的大大們指正錯誤,共同進步。或者直接私信
聲援博主:如果您覺得文章對您有幫助,可以點擊文章右下角推薦一下。您的鼓勵是作者堅持原創和持續寫作的最大動力!


免責聲明!

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



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