讓你負責秒殺系統架構,應該怎麼搞?

  • 2019 年 10 月 4 日
  • 筆記

寫在前面

秒殺系統特點是瞬時流量較大,我們先看幾個數據。

比如小米秒殺,三星秒殺都是瞬時搶走十幾萬台手機,天貓最快破億的一個旗艦店,雙十一峰值可達到60w以上的qps。後端的k-v集群峰值可達幾千萬qps,單機可達到30w qps,這些主要是讀流量,寫流量則小的多,比如對應時間點的減庫存寫操作也就幾kqps。

搭建一個秒殺系統的架構我們可以從以下幾個角度入手:

  1. 熱點隔離
  2. 動靜分離
  3. 削峰填谷
  4. 數據分層
  5. 熱點發現
  6. 以及個性化問題解決

熱點隔離

採用隔離方案是將秒殺系統中的熱點鏈路隔離出來,這也是設計秒殺系統的第一原則,梳理熱點數據和熱點鏈路。

我們不希望因為1%的熱點請求影響其他的99%將整個系統打垮,隔離出來之後我們可以進行後續的治理了。

秒殺系統我們可以從多個角度進行隔離:業務隔離,系統隔離,數據隔離。

業務隔離

秒殺基本屬於一種營銷策略,營銷活動,賣家的參加活動需要通過BD報備,報名參加,經過這種報名方式我們可以知道哪些是熱點業務了,包括參與秒殺活動的數據哪些是熱點,我們可以提前做好預熱。

系統隔離

在進行業務熱點識別之後,我們可以採用分離術,將熱點數據進行隔離,比如獨立部署1%和99%的熱點系統,針對於秒殺需求可以申請單獨的域名,目的還是不讓1%熱點請求影響整個集群。

數據隔離

秒殺場景中大部分數據是熱數據,可以啟用獨立的快取集群或者mysql集群存放熱點數據,目的還是隔離開,不讓1%影響整體集群存儲的數據問題。

通過以上三種方案我們知道整體上是進行隔離,不讓熱點請求熱點數據影響整個系統整個集群,其他的分離方案還有很多,比如按照用戶區分,不同用戶分配不同的cookie,在接入層路由到不同服務介面中。入口層可以對於請求介面進行限流策略。

服務層負載調用不同的服務介面。數據層採用數據打標方式進行熱點數據區分,目的是識別出熱點數據和普通數據。

動靜隔離

在進行了必要的隔離之後,我們接下來可以進行動靜分離操作了,這個也是解決大流量系統的第二個原則。

具體可以參考一些成熟的案例,比如【高訪問量系統的動態化架構設計】或開濤的京東詳情頁設計方案等。秒殺系統會將商品詳情頁獨立處理進行動靜分離。

  • 整個頁面快取到用戶瀏覽器
  • 如果強制刷新整個頁面,請求達到cdn
  • 實際有效請求只是點擊「秒殺」按鈕

這樣可以把90%的靜態數據快取到客戶端瀏覽器或cnd上,真正秒殺開始之後,點擊秒殺按鈕即可,而不會刷新整個頁面,這樣可以減少服務端響應的數據,而且大部分數據是靜態化的。由於秒殺的動態數據很少,整體上性能可以提升幾倍。

削峰填谷

對於防止機器秒殺造成的無效流量可以引入答題功能。

增加答題功能,時間控制到2s後,可以有效防止機器秒殺,

答題秒殺另一個功能是將瞬時秒殺流量拉長了,以前的1s進入的海量流量可以通過答題延長到幾秒到10s鍾,請求峰值會拉長,可以有效降低服務端壓力。

秒殺請求先到先得,後面的請求自然就沒有庫存了,到最後的下單步驟,真正的寫請求並發也就有限了。這種設計思路很普遍。

除了在客戶端做文章外,服務端可以採用鎖或者消息隊列方式將瞬時流量拉平。

數據分層

對於大流量系統,數據分層也是重要的設計原則,通過分層可以將請求做成漏斗設計,不同層次系統可以將無效請求過濾,漏斗末端才是真正有效請求,請求經過整個漏斗之後,有效請求並發會大大降低。

漏斗一般有以下幾種過濾:

  • 先做數據的動靜分離
  • 將90%的數據快取在客戶端瀏覽器
  • 將動態請求的讀數據Cache在Web端
  • 對讀數據不做強一致性校驗
  • 對寫數據進行基於時間的合理分片
  • 對寫請求做限流保護
  • 對寫數據進行強一致性校驗

大量靜態不需要校驗的數據放在離用戶近的地方,前端系統中可以校驗部分基本資訊,比如用戶的秒殺資格,商品狀態是否正常,答題是否正確,秒殺活動是否結束等。

在請求到達服務端再進行一次校驗,同時識別非法請求,判斷營銷價格是否符合活動要求,判斷積分是否滿足等,之後進行庫存檢查。

最後數據層保證數據的最終準確,比如庫存不能減成負數。

熱點發現

秒殺系統在大流量下的熱點數據是一個問題,我們通過隔離方式可以在活動開始之前識別出熱點數據。在活動進行時我們還可以增加一層保護,防止活動進行時流量激增造成的影響提前做好保護。

比如根據歷史成交記錄發現熱門商品,分析購物車記錄發現哪些商品好賣,通過類似方式可以動態識別出熱點商品,熱點數據。

對於活動進行中熱點數據的發現則是比較困難,比如一些數據活動期間突然成為了熱點數據,這樣對我們整個系統可能會有潛在的影響。

這種情況我們需要通過實時熱點數據分析,可以在3s內發現交易鏈路上的實時熱點數據,然後根據熱點數據,每個系統做好實時保護。

保護模式如下:

  • 構建一個非同步的可以收集交易鏈路上各個中間件產品如Tengine、Tair快取、HSF等本身的統計的熱點key(Tengine和Tair快取等中間件產品本身已經有熱點統計模組)。
  • 建立一個熱點上報和可以按照需求訂閱的熱點服務的下發規範,主要目的是通過交易鏈路上各個系統(詳情、購物車、交易、優惠、庫存、物流)訪問的時間差,把上游已經發現的熱點能夠透傳給下游系統,提前做好保護。比如大促高峰期詳情系統是最早知道的,在統計接入層上Tengine模組統計的熱點URL。
  • 將上游的系統收集到熱點數據發送到熱點服務台上,然後下游系統如交易系統就會知道哪些商品被頻繁調用,然後做熱點保護。

關鍵部分包括:

  • 這個熱點服務後台抓取熱點數據日誌最好是非同步的,一方面便於做到通用性,另一方面不影響業務系統和中間件產品的主流程。
  • 熱點服務後台、現有各個中間件和應用在做的沒有取代關係,每個中間件和應用還需要保護自己,熱點服務後台提供一個收集熱點數據提供熱點訂閱服務的統一規範和工具,便於把各個系統熱點數據透明出來。
  • 熱點發現要做到實時(3s內)。