架構之旅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語句更新庫存時,如果扣減庫存後,庫存數為負數,直接拋異常,利用事務的原子性進行自動回滾。
3.利用SQL語句更新庫存,防止庫存為負數
UPDATE [庫存表] SET 庫存數 - 1 WHERE 庫存數 - 1 > 0
如果影響條數大於1,則表示扣減庫存成功,否則不更新庫存,並退款。
五、秒殺場景下如何扣減庫存
(1)下單減庫存
因秒殺場景下,大部分使用者都是想直接購買商品的,可以直接用下單減庫存。
大量使用者和惡意使用者都是同時進行的,區別是正常使用者會直接購買商品,惡意使用者雖然在競爭搶購的名額,但是獲取到的資格和普通使用者一樣,所以下單減庫存在秒殺場景下,惡意使用者下單並不能造成之前說的缺點。
而且下單直接扣減庫存,這個方案更簡單,在第一步就扣減庫存了。
(2)將庫存放到redis快取中
查詢快取要比查詢資料庫快,所以將庫存數放在快取中,直接在快取中扣減庫存。
(3)使用量自增方式
可以先增加已使用量,然後與設定的庫存進行比較,如果超出,則將使用量減回去。
專案中用到了很多機制,但是沒有總結出來,學習架構需要不斷地總結。
作 者:
出 處:http://www.cnblogs.com/jackson0714/
關於作者:專注於微軟平臺的專案開發。如有問題或建議,請多多賜教!
版權宣告:本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結。
特此宣告:所有評論和私信都會在第一時間回覆。也歡迎園子的大大們指正錯誤,共同進步。或者直接私信我
聲援博主:如果您覺得文章對您有幫助,可以點選文章右下角【推薦】一下。您的鼓勵是作者堅持原創和持續寫作的最大動力!