秒殺活動的設計

來自我的博客 秒殺活動的設計

業務的基本說明

  1. 運營評估最高的併發會達到 10W(根據推廣的力度,以及以往的經驗)
  2. 業務現有的服務器架構 反向代理 4臺,前端機 8臺, db 2臺(主從),redis 2臺(主從)如下是服務器架構圖

clipboard.png

動靜分離

html 等靜態文件上CDN ,這方面壓力不大
後臺程序動態接口,必須支持高併發,用戶體驗必須作好
後端程序優化點(歡迎你們補充)php

  • 程序儘量的減小加載的文件
  • 程序減小沒必要要的網絡請求
  • redis 隊列來做 異步方式實現
// 後臺進程消費隊列 我的使用brpoplpush方法 取出數據並用存入另外隊列做數據備份
$block_expire_time = 0; # 設置阻塞等待時間爲永久
$redis->brpoplpush($key, $backup_key, $block_expire_time);
  • redis 緩存
  • 前端點擊按鈕請求後變灰,防止用戶重複點擊
  • 靜態文件上CDN
  • nginx的最大鏈接數設置爲550,防止鏈接數過大時所有到php,致使php服務掛了
  • 針對每一個用戶加併發鎖(redis),防止高併發狀況判斷條件被繞過,程序執行完後解鎖。
$lock_status = $redis->set($lock_key, 1, array("NX", "EX"=>$expire_time));

高併發下獎品超發問題

我的設計的方案:提早把每一個獎品放入 redis隊列,每一個key一個獎品,隊列的長度是獎品的數量,能夠保證獎品不會超發放
另外,假設使用
悲觀鎖,在更新數據的時候加鎖,其它的都爲等待狀態,不合適秒殺場景
樂觀鎖 基本是採用帶版本號更新,版本號匹配才能更新,其它的回滾,雖然保證的數據的安全不超發放,可是在高併發場景下,DB只有兩臺的時候,超過mysql 進程堆積確定會的, 超過最大鏈接數是怎麼辦,一系列的問題須要解決,因此該方案不合適html

程序壓測結果分析服務器能抗的併發

在平均響應時間300ms內,單臺qps 750 左右(保持300ms是公司壓測試的規範指標)
10臺機器(後面新增2臺到 8+2)一秒鐘能處理: 10 * 750 = 7500
保守的併發只有7500,與10w 差距大,須要在執行方案上解決,公司不可無限的申請web機器。
解決10W併發問題(資源有限的狀況)方案
在代理層作處理,根據權重擋掉93%的量,返回800(自定義),前端判斷是否爲800,是則提示火爆用戶重試(對應的方案設置友好一些)前端

活動的序列圖及說明

  1. 接口程序不鏈接查詢mysql數據庫
  2. 獎品的數據存放redis隊列,每一個獎品一個key,隊列長度是獎品的數量
  3. 用戶成功領取紅包(或搶購)時的代碼流程(不包括業務限制與防刷),從隊列獲取獎品成功,再入隊列(此隊列後臺消費入庫),返回給用戶領取成功。在用戶體驗上有所提高,但若是後臺隊列堆積太多,未能消費完成,用戶查看的紅包時是沒有對應記錄的,因此針對本身的需求做對應的優化。

clipboard.png

活動流程圖(開爺畫的)

clipboard.png

相關文章
相關標籤/搜索