設計秒殺系統筆記

設計原因:

爲什麼要針對秒殺設計一個完善的方案?因爲系統可能會因爲1%的秒殺業務影響其餘99%正常業務的運行,所以需要將秒殺系統獨立出來。

待解決問題:

主要解決兩個問題:併發讀、併發寫。

整體架構要求:

概括爲:"穩、準、快",即對應"高可用、一致性、高性能",其介紹分別如下:

高可用:保證系統的高可用和正確性,設計PlanB進行兜底。

一致性:保證秒殺減庫存中的數據一致性。

高性能:涉及大量併發讀寫,所以需要支持高併發,從動靜分離、熱點發現與隔離、請求削峯與分層過濾、服務端極致優化來介紹。

五個架構原則(4要1不要):

數據儘量少:包含請求和響應的數據,因爲網絡傳輸需要時間。可簡化秒殺頁面、減少數據庫打交道。

請求數儘量少:瀏覽器渲染頁面包含額外請求,比如以來了css、js、圖片等定義爲額外請求,這些請求儘可能少,若請求域名不一致,還涉及DNS解析,耗時更久,可採用合併方法如:http://xxx.com/tm/modes??module-preview/index.xtpl.js,module-jhs/index.xtpl.js ,這個在服務器依舊是單獨存放,只是提供了一個組件解析這個url。比如以下是淘寶的一個靜態資源鏈接:

路徑儘量短:這裏的路徑表示節點。每個節點都會產生新的socket連接,一個節點的可用性是99.9%,經過五個節點後就是五次方爲99.5%。方法可以是服務內部RPC調用變爲jvm內部調用。

依賴儘量少:將服務分級,比如將支付服務作爲0級,優惠券是1級,要避免0級系統被1級系統拖垮。

不要有單點:單點意味着沒有備份。將服務無狀態化,即避免服務與機器綁定。可設置配置中心映射。

注:數據、請求數、路徑、依賴、單點。但是其實這些原則會產生衝突,如請求數量少中的合併請求會使單次請求的數據量變大,這與數據儘量少違背。所以需要我們做一個平衡。

秒殺系統的大體涉及結構:

1 頁面徹底動靜分離,使得用戶秒殺時不需要刷新整個頁面,降低刷新請求數。

2 服務器緩存秒殺商品,直接調用緩存層,無需穿透到數據庫層找數據。

3 增加流量限流保護,防止最g壞情況。 

如何動靜分離:

把用戶請求數據(如HTML)分爲"動態數據"和"靜態數據"。

 

動態數據與靜態數據區別:確定輸出的數據是否含訪問者個性化數據如 個人信息、cookie等私密數據。

 

區別動靜數據的作用:區分了動靜數據,就可以將靜態數據緩存,提高效率。

 

如何對靜態數據做緩存:

1. 將靜態數據放在離用戶最近的地方,如CDN、用戶瀏覽器、服務端的Cache。

2. 做靜態化改造,直接緩存HTTP連接。Web服務器根據請求URL直接取出HTTP響應頭、響應體直接返回。

3. 選擇誰來緩存靜態數據,如可在web服務器層做緩存,屏蔽java層的弱點,不在java層做緩存。

 

如何做動靜分離改造:

1. URL唯一化。如每個商品鏈接爲:http://item.xxx/xxxx?id=xxx 來作爲緩存的key,用於緩存整個HTTP連接。

2. 分離請求,含用戶信息相關、時間、地獄相關,這些都可以通過異步請求獨立獲取。

3. 服務器返回的信息可去掉cookie。如Vanish可用unset req.http.cookie去掉cookie。

 

動態內容處理方案:

ESI:web代理服務器做動態請求時,將動態內容插入靜態頁面,然後全部返回。

CSI:異步js請求,性能最佳,但是有一定時延,可能對用戶體驗不好。

 

動靜分離的幾種架構方案:

1. 實體機單機部署:將虛擬機運行的Java應用換成實體機

優點:無網絡瓶頸、可使用大內存。

          提升命中率,減少Gzip壓縮。

          減少cache失效壓力,因爲採用定時失效,如3分鐘失效。

2 統一Cache層:即抽離cache出來作爲一個獨立的集羣。可設置二級Cache,放置回原(原服務器)

 

3. 上CDN:可增加二級Cache防止回原(原服務器)。

二八原則(針對性處理熱點數據):

爲什麼要針對性處理:熱點數據會大量佔用服務資源,0.1%業務會搶佔系統90%以上的資源。

 

什麼是熱點:

    熱點分爲熱點操作和熱點數據,其中熱點操作是一種優化的方式,將會在秒殺的操作優化講解。

    熱點數據分爲動態、靜態熱點數據如下:

    -靜態熱點數據即可提前預測數據如數據分析出哪種更熱門、一個商品做活動等。

    -動態熱點數據不可預測,如抖音廣告然後突然火了。

 

如何發現熱點數據:

    發現靜態熱點數據:強制讓賣家通過報名方式提前把熱點數據篩選出來緩存,但是增加了賣家的工作量,也不夠實時。也可以根據每日訪問數進行統計,然後緩存TOP N的商品。

 

    發現動態熱點數據:抽離出一箇中間件用於收集搜索、商品詳情、購物車等關鍵熱點業務的點擊數據,然後異步記錄到日誌,然後根據規則判斷是否熱點數據後緩存在隊列中(因爲熱點數據一般是臨時的,所以可採用LRU算法淘汰)。

 

流量削峯怎麼做:

爲什麼要削峯:穩定服務端,節省資源,本質是延緩用戶請求發出,減少和過濾無用請求(遵循請求書儘量少原則)。

 

削峯思路:排隊、答題、分層過濾

    排隊:消息隊列緩存大量併發,把原來的一步操作變成兩步。雖然違背了增加訪問路徑原則,但是防止了系統崩潰。

    答題:可防止爬蟲等的自動搶購的腳本。延緩請求從之前的1s內延緩到2-10s,對事件進行了分片,減緩服務器壓力,如微信的搖一搖、支付寶休一休。也可限制答題時間間隔。

    分層過濾:分層爲:CDN->前臺讀系統(商品詳情繫統)->後臺寫系統(交易系統)->DB

大部分數據和流量都在CDN獲取,攔截了大部分讀的數據。

經過第二層(前臺讀系統)儘量走Cache。

到第三層(後臺寫系統),做數據校驗、限流,進一步減少數據量和請求。

最後在數據層完成強一致性校驗。

 

分層過濾核心思想:各層過濾無效請求,所以必須對數據做分層校驗,其校驗原則如下:

將動態請求的讀數據緩存在瀏覽器本地,過濾無效數據讀。

對讀數據不做強一致性校驗,較少一致性校驗帶來的性能問題。

對寫數據基於時間的合理分片,過濾過期失效請求。

對寫數據做強一致性校驗,只保留有效數據。

影響性能的因素及其可優化處:

影響服務端性能的因素:QPS、響應時間(RT)

    計算公式:QPS = (1000ms / 響應時間) * 線程數量,真正影響性能的是CPU執行時間。


    再來分析下線程數是否對QPS的影響:不是線程數越多,QPS越高,因爲線程上下文切換有消耗。所以需要合理的設置線程數,一般的計算公式爲:線程數 = [(線程等待時間 + 線程CPU時間) / 線程CPU時間] * CPU數量,當然最好的方式是性能測試來確認。

 

如何發現瓶頸:就緩存系統而言,制約的是內存。存儲系統的瓶頸是I/O。

 

秒殺系統的大部分瓶頸在CPU(使用JProfiler、YourKit),但不一定是CPU,有可能是其他部分,比如QPS達到極限時,CPU使用率是否超過95%,如果不是則可能是鎖限制或過多本地I/O等待發生。

 

如何優化系統:

減少編碼:java編碼速度慢,涉及字符串操作(輸入輸出操作、I/O操作)比較消耗CPU資源。原因是磁盤、網絡IO都需要將字符串轉爲字節,這個轉換必須查表編碼。可通過(OutputStream()直接進行流輸出),可提高30%.

減少序列化:序列化與編碼同時發生,所以需要減少。儘量減少RPC,將關聯性強的應用服務合併。

Java極致優化:對大流量Web系統做靜態化改造;直接使用Servlet,繞過框架多餘處理邏輯;直接輸出流數據。

併發讀優化:秒殺系統單機緩存。不要求讀一致性,但是寫數據的時候要求強一致性。

秒殺系統設計的核心邏輯:

秒殺系統最重要要求是 "不要超賣",關鍵在於減庫存。

 

減庫存方式(三種):

下單減庫存:一定不會出現超賣情況,但是有些人下單完不付款會影響其他人。

付款減庫款:付款減庫存,可能會因爲併發高導致付款時已經賣光,付不了款。

預扣庫存:最常用,如下單後扣庫存,保留十分鐘,在十分鐘內未付款就不保留。如果付款時發現庫存不足則不允許付款。

 

減庫存存在的問題:在下單減庫存、預扣庫存的情況下,有競爭對手惡意多賬號下單導致庫存降爲0,那商品就無法正常賣。

    解決辦法:指定反作弊措施,如給經常下單不買的用戶打標識、設置最大購買書、設置重複下單不付款操作數。

 

秒殺減庫存極致優化:

    秒殺商品減庫存放緩存如redis。給熱點商品提供獨立的緩存層、DB層集羣。使用排隊如應用層排隊、數據庫層排隊(阿里針對mysql的innodb做了補丁程序patch可對單行記錄做併發排隊)解決數據庫併發鎖問題。

設計Plan B兜底方案:

再牛逼的系統也會問題,比如超大流量導致宕機,出現最壞情況,所以需要設計Plan對應高可用性。

 

各階段處理操作:

架構階段:考慮拓展性和容錯性,避免系統出現單點問題。

編碼階段:保證代碼健壯性,合理設置超時退出機制,對於異常捕獲後需要一個默認處理。

測試階段:保證最壞情況下,也有相應處理流程。

發佈階段:需要有備份用於回滾。

運行階段:系統監控和報警,如cat監控系統。

故障發生:及時止損,如下架標錯價商品。

 

運行階段詳細處理:

降級:限制或關閉某些非核心功能,留給核心功能。如展示成功記錄由30條變成5條。

限流:設置一個QPS閾值,達到則排隊或丟棄。

拒絕:當連接數過大,cpu負載達到90%,就拒絕請求。

讀自:許令波-《如何設計一個秒殺系統》
--------------------- 
作者:Lidisam 
來源:CSDN 
原文:https://blog.csdn.net/qq_28666081/article/details/83043215 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章