第六節:秒殺業務/超買超賣的幾種解決思路

https://www.cnblogs.com/yaopengfei/p/12418229.htmlhtml


一. 加鎖redis

1.  單個IIS(即單進程),經過在代碼裏lock線程鎖便可。數據庫

2.  若是是IIS集羣,多個IIS同時請求DB,那麼lock線程鎖就鎖不住了,這裏就須要引入Redis分佈式鎖,全部請求先去Redis加鎖→秒殺→解鎖,實際上多個IIS請求最終到數據庫 依次前後進行的服務器

這個時候,若是說Redis扛不住這個併發,搞Redis集羣,Redis集羣中的鎖也是依次進行的,集羣中必須上一個redis解鎖,下一個才能加鎖,因此這裏引入Redis集羣,是爲了應對高併發問題,是爲了防止redis宕機,並不能加快最終秒殺的速度,實際上和單體Redis速度是同樣的。併發

二. 庫存放redis裏異步

1. 單體Redis沒問題,提早把商品的庫存加載到Redis中去,讓整個流程都在Redis裏面去作(利用Redis原子性),而後等秒殺介紹了,再異步的去修改庫存就行了。分佈式

2. 集羣Redis有問題。高併發

  好比如今庫存只剩下1個了,咱們高併發嘛,4個redis服務器一塊兒查詢了發現都是還有1個,那你們都以爲是本身搶到了,就都去扣庫存,那結果就變成了-3。spa

也能夠解決:線程

Lua腳本是相似Redis事務,有必定的原子性,不會被其餘命令插隊,能夠完成一些Redis事務性的操做。這點是關鍵。

知道原理了,咱們就寫一個腳本把判斷庫存扣減庫存的操做都寫在一個腳本丟給Redis去作,那到0了後面的都Return False了是吧,一個失敗了你修改一個開關,直接擋住全部的請求,而後再作後面的事情嘛。

三. 放消息隊列裏

1. 單體或者集羣Redis

     把全部的請求放到Redis隊列中,而後開啓一個線程去  出隊執行秒殺業務(秒殺業務執行完,下一個纔出隊),實際上到數據庫仍是 一個接着一個進行。

注意: 若是是開多個線程出隊執行秒殺業務, 或者 即便單線程出隊,而後秒殺 ,出隊和秒殺是分開執行,  一樣會存在上一個秒殺業務沒有執行完,下一個又進來了。

還要注意:若是秒殺業務是集羣,即便是依次出隊,打到DB上仍是會存在上述問題,且無法保證原先隊列中的前後順序了。

   

2. 聽說小米的解決方案:(不當即操做)

  你們先發起搶的請求,服務器端把請求按先到先存規則放進消息隊列,當消息隊列到了最大值就說明是理論上的搶完了, 這時再處理消息隊列生成訂單, 你們過幾分鐘就能發現有沒有搶獲得, 搶到的讓他們繼續付款。

相關文章
相關標籤/搜索