面試 如何設計乙個秒殺系統

2021-10-23 20:27:55 字數 1542 閱讀 4404

將請求盡量攔截在系統上游,同時對請求進行限流和削峰。大體架構如下

限流:前端答題或驗證碼,來分散使用者的請求

禁止重複提交:限定每個使用者發起一次秒殺後,需等待才可以發起另一次請求,從而減少使用者的重複請求

本地標記:使用者成功秒殺到商品後,將提交按鈕置灰,禁止使用者再次提交請求

動靜分離:將前端靜態資料直接快取到離使用者最近的地方,比如使用者瀏覽器、cdn 或者服務端的快取中

限流:遮蔽掉無用的流量,允許少部分流量走後端。假設現在庫存為 10,有 1000 個購買請求,最終只有 10 個可以成功,99% 的請求都是無效請求。

削峰:秒殺請求在時間上高度集中於某乙個時間點,瞬時流量容易壓垮系統,因此需要對流量進行削峰處理,緩衝瞬時流量,盡量讓伺服器對資源進行平緩處理

非同步:將同步請求轉換為非同步請求,來提高併發量,本質也是削峰處理

利用快取:建立訂單時,每次都需要先查詢判斷庫存,只有少部分成功的請求才會建立訂單,因此可以將商品資訊放在快取中,減少資料庫查詢。

負載均衡:利用 nginx 等使用多個伺服器併發處理請求,減少單個伺服器壓力

服務端的優化

服務端應該使用樂觀鎖更新庫存,以防止出現商品超賣的問題。

悲觀鎖雖然可以解決超賣問題,但是加鎖的時間可能會很長,會長時間的限制其他使用者的訪問,導致很多請求等待鎖,卡死在這裡,如果這種請求很多就會耗盡連線,系統出現異常。樂觀鎖預設不加鎖,更新失敗就直接返回搶購失敗,可以承受較高併發

redis 計數限流

根據前面的優化分析,假設現在有 10 個商品,有 1000 個併發秒殺請求,最終只有 10 個訂單會成功建立,也就是說有 990 的請求是無效的,這些無效的請求也會給資料庫帶來壓力,因此可以在在請求落到資料庫之前就將無效的請求過濾掉,將併發控制在乙個可控的範圍,這樣落到資料庫的壓力就小很多

詳細的限流演算法可以採用令牌桶:

令牌桶演算法的流程:

3. redis 快取商品庫存資訊

雖然限流能夠過濾掉一些無效的請求,但是還是會有很多請求落在資料庫上,實時查詢庫存的語句被大量呼叫,對於每個沒有被過濾掉的請求,都會去資料庫查詢庫存來判斷庫存是否充足,對於這個查詢可以放在快取 redis 中,redis 的資料是存放在記憶體中的,速度快很多。

快取和資料一致性

快取和 db 的一致性是乙個討論很多的問題,推薦看參考本人的另一篇部落格,可以採用簡單的cache aside 策略即先把資料存到資料庫中,成功後,再去刪除快取或者讓快取失效。也可以使用樂觀鎖來進行資料庫的庫存修改

訊息佇列削峰

伺服器的資源是恆定的,你用或者不用它的處理能力都是一樣的,所以出現峰值的話,很容易導致忙到處理不過來,閒的時候卻又沒有什麼要處理,因此可以通過削峰來延緩使用者請求的發出,讓服務端處理變得更加平穩。

如何設計乙個秒殺系統

秒殺場景一般會在電商 舉行一些活動或者節假日在12306 上搶票時遇到。對於電商 中一些稀缺或者 商品,電商 一般會在約定時間點對其進行限量銷售,因為這些商品的特殊性,會吸引大量使用者前來搶購,並且會在約定的時間點同時在秒殺頁面進行搶購。限流 鑑於只有少部分使用者能夠秒殺成功,所以要限制大部分流量,...

如何設計乙個秒殺系統

秒殺場景一般會在電商 舉行一些活動或者節假日在12306 上搶票時遇到。對於電商 中一些稀缺或者 商品,電商 一般會在約定時間點對其進行限量銷售,因為這些商品的特殊性,會吸引大量使用者前來搶購,並且會在約定的時間點同時在秒殺頁面進行搶購。限流 鑑於只有少部分使用者能夠秒殺成功,所以要限制大部分流量,...

如何設計乙個秒殺系統

秒殺一般是訪問請求數量遠遠大於庫存數量,只有少部分使用者能夠秒殺成功。秒殺業務流程比較簡單,一般就是下訂單減庫存。瀏覽器端 js 服務端控制器層 閘道器層 服務層利用快取應對讀請求 對類似於12306等購票業務,是典型的讀多寫少業務,大部分請求是查詢請求,所以可以利用快取分擔資料庫壓力。利用快取應對...