開發與維運

如何設計秒殺系統?

秒殺系統是常見的一種系統設計類型,在電商業務中的應用非常普遍。同時也是面試中問得比較多的。

如果說程序 = 算法 +數據結構的話,那麼系統 = 服務 + 數據存儲。所以系統設計中,我們更多的是圍繞服務和數據存儲來討論。

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

梳理下用戶端的流程圖:

image.png

根據系統設計的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服務

秒殺系統服務設計大致如下:

image.png

第三步 - Storage存儲

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

image.png

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

image.png

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

image.png

樂觀鎖流程:

image.png

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

推薦免費體驗九章的《系統架構設計》,在免費試聽章節裡,還講到了Redis下的秒殺系統數據庫設計。

image.png

幾個關於Redis的常見問題:

什麼時候把庫存寫入到Redis?
秒殺活動創建/維護時寫入Redis。

如何保證活動數據庫和庫存數據一致?
可以使用分佈式事務或消息隊列。

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

image.png

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

image.png

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

如何防止商品被超賣?
把庫存數據放入到緩存中,利用緩存的原子特性保證同時只有一個線程操作庫存。

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

4S分析法的第四步 - Scale擴展

對於秒殺系統來說,就是高併發場景下如何優化系統。推薦大家通過完整視頻瞭解如何進行系統優化和升級。

前面說過,秒殺系統是電商業務中最常見的,在實際面試當中,系統架構設計的考察標準是:面試者獨立設計一個大型的系統,它在現實中是可work的,同時在高併發的情況下仍具有高可用性。

對許多缺少工作經驗的應屆生,以及大量沒機會參與大型系統設計、日常都在“擰螺絲”的初級程序員來說,明明不具備架構的能力但面試的時候又經常遇到,拿到設計類題目就懵了!

九章的《系統架構設計》覆蓋了18大系統架構設計知識點和麵試題。通過大量調研,囊括了最熱門、高頻的18大設計類題型包括了:

  • 秒殺/訂票系統
  • IM系統
  • 協同文檔編輯系統
  • 谷歌搜索系統
  • 用戶登陸/註冊系統
  • 網站系統(API設計/短URL)
  • 數據庫
  • 容器技術(K8S/Docker)
  • MLE機器學習系統
    ……

想要嘗試自己設計一個秒殺系統,或者對國內熱門的系統設計感興趣的同學們,不妨來試聽一下,好的學習方式永遠是自己動手實現。

Leave a Reply

Your email address will not be published. Required fields are marked *