秒殺設計實現方式

秒殺系統中涉及到的很多技術點也是一二線大廠面試重點考察的點。秒殺系統也是我在面試中問得比較多的,時間充裕的同學可以看下 B 站阿里面試官關於秒殺系統的乾貨分享:淘寶秒殺系統怎麼設計?

舉個簡單例子:雙 11,商家以 4499 的價格上架了某 iphone,比官網價格便宜了 1000 元,庫存總數 10 臺,運營設置 11/11 00:00 活動生效,一人只能購買 1 臺,商品售完爲止。

梳理下用戶端的業務流程:

根據九章算法獨家系統設計 4S 分析法,第一步 Scenario 場景。需要確定設計哪些功能,承受多大的訪問量?

秒殺業務通常具有如下特點:

瞬間併發量大:大量用戶會在同一時間搶購,網站流量瞬間激增。

庫存少:訪問數量遠遠大於庫存數量,只有極少數人成功。

業務流程簡單:流程短,立即購買 - 下單 - 減庫存。

前期預熱:對於還未開啓活動的秒殺商品,以倒計時的方式顯示,只能訪問不能下單。

這裏有個常見概念 QPS(Query Per Second),即一秒內可以處理的請求數量。假如一個服務的 RT 是 20ms,則 QPS 爲 50,這裏計算的是單機單線程 QPS,如果計算集羣的話,需要考慮集羣數量和線程數量。

這時候需要確認秒殺商品的請求 QPS 是多少。如果面試官說峯值大概量級在 100 萬,那麼按照服務單線程 QPS 是 50,單臺最大線程數按 3 來計算的話,單臺機器最大支撐 150 的 QPS,那麼至少需要 100W/150=6667 臺機器。

常見的組件最大 QPS,mysql 單機 1000QPS,Redis 單機 10 萬 QPS。

第二步,Service 服務。秒殺系統服務設計大致如下

第三步,Storage 存儲,數據是如何存儲和訪問的。爲每個服務選擇合適的存儲結構,然後細化數據表結構。這個例子中,秒殺系統數據庫設計如下

於是我們可以得到秒殺活動中,數據庫之間的關係如圖所示

接下來就是 mysql 扣庫存了。秒殺系統一定會遇到的就是併發問題,這裏說下樂觀鎖和悲觀鎖。

悲觀鎖的流程如下:

樂觀鎖流程如下:

可以看到悲觀鎖的問題是會佔用大量的線程資源,可能導致 mysql 的線程耗盡。在對於數據一致性要求非常高的場景中,一般用悲觀鎖;而樂觀鎖在 version 變動頻繁的情況下則不適用,比如這裏的秒殺系統就不太適合用樂觀鎖,因爲庫存變化太快了。

另外可以再看下 Redis 下的秒殺系統數據庫設計。

幾個關於秒殺系統中 Redis 的常見問題:

  1. 什麼時候把庫存寫入到 Redis?

秒殺活動創建 / 維護時寫入 Redis。

  1. 如何保證活動數據庫和庫存數據一致?

可以使用分佈式事務或消息隊列。

分佈式事務:保證多個數據庫的操作同時成功或者同時失敗。對強一致性有要求的業務場景可以考慮使用分佈式事務,比如銀行轉賬

消息隊列:基於生產者 / 消費者模型的組件,一般實現異步任務(非實時處理)時會引入消息隊列。消息隊列的好處是任務可以慢慢處理,不必同步處理等着響應結果。目前主流的消息隊列有 RocketMQ、Kafka 等。使用場景除了異步任務之外,一般還用於失敗的情況下重試處理,重複消費直到消費成功。

  1. 下單減庫存 / 支付減庫存?

下單鎖定庫存,支付減庫存。

  1. 如何防止商品被超賣?

把庫存數據放入到緩存中,利用緩存的原子特性保證同時只有一個線程操作庫存。

  1. 庫存寫回數據庫的時機?

採用定時任務同步 Redis 的數據寫回數據庫。

版權聲明:本文爲 CSDN 博主「九章算法」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/JiuZhang_ninechapter/article/details/109329902

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/PClrU8DGWhBcXnQQ7p3aNQ