秒殺商品設計

秒殺商品設計

前端限制

前端控制,不能重複點擊

精簡sql

典型的一個場景是在進行扣減庫存的時候,傳統的做法是先查詢庫存,再去update。 這樣的話需要兩個sql,而實際上一個sql我們就可以完成的。
可以用這樣的做法: update miaosha_goods set stock =stock-1 where goos_id ={#goods_id}
and version = #{version} and sock>0 ;
這樣的話,就可以保證庫存不會超賣並且一次更新庫存,還有注意一點這裏使用了版本號的樂觀鎖,相比較悲觀鎖,它的性能較好。

同一個用戶xx秒內重複請求直接拒絕

具體多少秒需要根據實際業務和秒殺的人數而定,一般限定爲10秒。
具體的做法就是通過redis的鍵過期策略,首先對每個請求都從 String value = redis.get(userId) ;
如果獲取到這個 value爲空或者爲null,表示它是有效的請求,然後放行這個請求。如果不爲空表示它是重複性請求,直接丟掉這個請求。
如果有效,採用 redis.setexpire(userId,value,10).value
可以是任意值,一般放業務屬性比較好,這個是設置以userId爲key,10秒的過期時間(10秒後,key對應的值自動爲null)

使用redis限流

限流的實現可以直接使用 GuavaRateLimit 方法,分佈式的話,可以緩存在redis

使用redis加載商品,數據庫樂觀鎖更新

  1. 將商品數據加載到redis
  2. 用戶進來查看redis中的庫存數量num,庫存不足直接拋出
  3. 進入數據庫,更新數據庫庫存(需要注意的是,這裏要進行樂觀鎖判斷,並且還要校驗庫存數量num,可以正好一起做樂觀鎖判斷),不匹配也直接拋出
  4. 更新db後,更新redis緩存

這裏有一個樂觀鎖判斷,如果一個線程A在走上面的流程,線程B進入,查看到庫存,在進入步驟3進行更新數據時,因爲緩存中庫存與數據庫中的庫存不一致,導致更新失敗。

異步下單

爲了提升下單的效率,並且防止下單服務的失敗。 需要將下單這一操作進行異步處理。
最常採用的辦法是使用隊列,隊列最顯著的三個優點: 異步、削峯、解耦

這裏可以採用rabbitmq,在後臺經過了限流、庫存校驗之後,流入到這一步驟的就是有效請求。 然後發送到隊列裏,隊列接受消息,異步下單。
下完單,入庫沒有問題可以用短信通知用戶秒殺成功。 假如失敗的話,可以採用補償機制,重試。

服務降級

假如在秒殺過程中出現了某個服務器宕機,或者服務不可用,應該做好後備工作。 之前的博客裏有介紹通過Hystrix進行服務熔斷和降級,可以開發一個備用服務。
假如服務器真的宕機了,直接給用戶一個友好的提示返回,而不是直接卡死,服務器錯誤等生硬的反饋。

參考:

秒殺

面試官問我:如何設計一個秒殺場景?

Redis隊列實現Java版秒殺系統(無腳本、可用於生產)

Java上億級別秒殺系統優化 ,實現真正的高性能高併發!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章