談談秒殺系統的落地方案

ForestXie發表於2017-07-04

昨天的文章給秒殺系列開了一個頭,今天會集中講一下實現一個秒殺系統的思路和方案,不代表這就是最好的方案或者最佳實踐,而是希望通過這篇文章,能起到拋磚引玉的作用,希望有更佳的思路提供出來。


秒殺系統要解決的技術挑戰

1. 短時間內的超高訪問量對後臺服務的衝擊。秒殺期間,來自外部請求產生的QPS會是平時的10~100倍。

2. 資料庫的讀寫壓力陡增。大量的併發寫,會造成資料庫的行鎖處於無法釋放的狀態,大量的執行緒排隊進而造成服務請求超時失敗。

3. 網路頻寬資源會因為秒殺被大量佔據掉。假設秒殺頁面的大小為150K,如果最大併發連線數為20000,那麼應用伺服器至少需要支援的頻寬>3G。


秒殺系統開發前的準備


1. 所有頁面的靜態資源走CDN,CSS, JS和圖片放入CDN後,利用遍佈全國的CDN節點,降低頻寬和靜態伺服器的壓力,避免網路頻寬成為業務瓶頸。

2. 準備獨立的伺服器,秒殺系統單獨部署,包括使用單獨域名,避免秒殺業務對正常業務的系統的衝擊和影響。

3. 建立效能測試的環境,上線前根據本次秒殺的業務目標和流量預估,制定效能測試計劃,只有通過效能測試後,才能真正上線。


秒殺系統的架構設計


1. 前端的設計

在整個活動過程中,前端頁面應該是如下狀態:


秒殺開始前,秒殺按鈕灰掉為“未開始”,不可點選。

秒殺進行中,秒殺按鈕可以點選下單。

秒殺結束後,秒殺按鈕灰掉為“已結束”,不可點選。


所以我們需要做以下幾件事:


1. 秒殺產品的介紹,詳情,引數等等,全部靜態化,切勿通過後臺API查詢更新,減輕後端的壓力。

2. 使用者點選“下單”後,按鈕置灰,禁止使用者重複提交請求,限制使用者在60秒之內只能提交一次請求。

3. “下單”的URL在活動開始前不可露出或者生效,否則容易被使用工具繞過瀏覽器提前下單。導致活動還未開始,已經開始下單這個大黑洞。正確的做法是活動開始前,通過更新JS檔案露出下單的URL。

4. 下單過程中,涉及到訂單引數的修改全部關掉,比如,購買的金額,產品的份額等等,降低訂單服務的壓力。



2. 服務層的設計


服務層的設計,如下圖所示:

談談秒殺系統的落地方案


  1. 確保所有服務的快取是獨立分開,相互不影響。

  2. 按照昨天文章寫到的那樣,檢查使用者的身份和條件,將無效的使用者請求阻止在業務層之前。

  3. 所有讀請求全部走快取,Redis or MemCached, 也可以考慮走讀庫,請注意流量的分配。

  4. 秒殺開始前,所有產品的屬性和庫存預載入到快取中,秒殺過程中不主動更新資料庫,庫存資料延遲非同步更新。

  5. 對於訂單的寫請求,加快取,並做請求佇列,每次只透過有限的寫請求去資料層,扣除庫存成功均成功再進行下一批訂單資料的更新,如果庫存不夠則佇列裡的寫請求全部直接返回,儘可能阻止無效的請求穿透到資料層;

  6. 當瞬間秒殺產品庫存太大,造成的Redis寫暴增,可能造成執行緒阻塞最後寫超時對於如上的異常,新增一個秒殺開關,大量異常時開關關閉停止一切秒殺活動,以免造成更大的損失。


建立秒殺系統的監


為了應對秒殺過程中的各種突發情況,我們還需要建立有效的監控手段來保障秒殺的過程。


  1. 監控Redis呼叫效能,主要是看讀和寫的效能兩個指標。

  2. 監控各個關鍵介面的執行情況,特別是下單介面的狀態,看是否有大量請求timeout或者異常的情況出現,關注失敗的訂單數,設定預警閾值。如果超過閾值,報警並採取緊急處理措施,例如關閉秒殺,進行服務降級。

  3. 監控資料庫的效能,密切關注訂單寫庫的執行狀態和讀庫的同步情況。



掃描二維碼或手動搜尋微信公眾號【架構棧】: ForestNotes

歡迎轉載,帶上以下二維碼即可

談談秒殺系統的落地方案


相關文章