由微視春節集卡瓜分活動,看高可用秒殺系統的架構設計
微視春節項目中的集卡瓜分活動,是一個典型流量洪峰下的秒殺場景,本文作者參與其中,對高可用秒殺系統的架構設計做了一些思考和總結。(流量洪峰所帶來的一系列挑戰,足以激發每位程式設計師的鬥志。雲加社區將推出「高可用架構之流量洪峰」系列內容,歡迎關注)。
一、背景簡介
如今的互聯網已經在海量服務領域有了很成熟的理論,有很多在流量洪峰下的實踐。而微視春節項目中的集卡瓜分活動,主要環節包括發卡、集卡、瓜分等流程,涉及到高並發、降級預案等,是一個典型流量洪峰下的秒殺場景。我有幸參與其中,從0到1完整踐行了海量服務。本文是對高可用秒殺系統的架構設計的一些思考,希望對讀者有所幫助。
二、秒殺系統剖析
1. 秒殺系統面臨的難點
(1)如何保證友好的用戶體驗?
用戶不能接受破窗的體驗,例如:系統超時、系統錯誤的提示,或者直接404頁面。
(2)如何應對瞬時高並發流量的挑戰?
木桶短板理論,整個系統的瓶頸往往都在DB,如何設計出高並發、高可用系統?
2. 如何設計秒殺系統?
(1)典型的互聯網業務結構
下圖展示了一個典型的互聯網業務結構抽象圖,用戶完成一個寫操作,一般會通過接入層和邏輯層,這裡的服務都是無狀態,可以通過平行拓展去解決高並發的問題;到了DB層,必須要落到介質中,可以是磁碟/ssd/記憶體,如果出現key的衝突,會有一些並發控制技術,例如cas/加鎖/串列排隊等。
(2)直筒型架構設計
直筒型架構設計,指的是用戶請求1:1的洞穿到DB層,如下圖所示。在比較簡單的業務中,才會採用這個模型。隨著業務規模複雜度上來,一定會有DB和邏輯層分離、邏輯層和接入層分離。
(3)漏斗型架構設計
漏斗型架構設計,指的是,用戶的請求,從客戶端到DB層,層層遞減,遞減的程度視業務而定。例如當10萬人去搶1個物品時,DB層的請求在個位數量級,對於秒殺系統來講,漏斗型架構設計就是比較理想的模型,如下圖所示。
漏斗型的架構設計,是高並發的基礎,能夠做到:
-
及早發現,及早拒絕
-
Fast Fail
-
前端保護後端
3. 如何實現漏斗型系統?
漏斗型系統需要從產品策略/客戶端/接入層/邏輯層/DB層全方位立體的設計。
(1)產品策略
-
輕重邏輯分離,以秒殺為例,將搶到和到賬分開;
– 搶到,是比較輕的操作,庫存扣成功後,就可以成功了。
– 到賬,是比較重的操作,需要涉及到到事務操作。
-
用戶分流,以整點秒殺活動為例,在1分鐘內,陸續對用戶放開入口,將所有用戶請求打散在60s內,請求就可以降一個數量級。
-
頁面簡化,在秒殺開始的時候,需要簡化頁面展示,該時刻只保留和秒殺相關的功能。例如,秒殺開始的時候,頁面可以不展示推薦的商品。
(2)客戶端
-
重試策略非常關鍵,如果用戶秒殺失敗了,頻繁重試,會加劇後端的雪崩。如何重試呢?根據後端返回碼的約定,有兩種方法:
– 不允許重試錯誤,此時UI和文案都需要有一個提示。同時不允許重試;
– 可重試錯誤,需要策略重試,例如二進位退避法。同時文案和UI需要提示。
-
UI和文案,秒殺開始前後,用戶的所有異常都需要有精心設計的UI和文案提示。例如:【當前活動太火爆,請稍後再重試】【你的貨物堵在路上,請稍後查看】等。
-
前端隨機丟棄請求可以作為降級方案,當用戶流量遠遠大於系統容量時,人工下發隨機丟棄標記,用戶本地客戶端開始隨機丟棄請求。
(3)接入層
-
所有請求需要鑒權,校驗合法身份。
如果是長鏈接的服務,鑒權粒度可以在session級別;如果是短鏈接業務,需要應對這種高並發流量,例如cache等。
-
根據後端系統容量,需要一個全局的限流功能,通常有兩種做法:
– 設置好N後,動態獲取機器部署情況M,然後下發單機限流值N/M。要求請求均勻訪問,部署機器統一。
– 維護全局key,以時間戳建key。有熱key問題,可以通過增加更細粒度的key或者定時更新key的方法。
-
對於單用戶/單IP需要頻控,主要是防黑產和惡意用戶。如果秒殺是有條件的,例如需要完成xxx任務,解鎖資格,對於獲得資格的步驟,可以進行安全掃描,識別出黑產和惡意用戶。
(4)邏輯層
-
邏輯層首先應該進入校驗邏輯,例如參數的合法性,是否有資格,如果失敗的用戶,快速返回,避免請求洞穿到DB。
-
非同步補單,對於已經扣除秒殺資格的用戶,如果發貨失敗後,通常的兩種做法是:
– 事務回滾,回滾本次行為,提示用戶重試。這個代價特別大,而且用戶重試和前面的重試策略結合的話,用戶體驗也不大流暢。
– 非同步重做,記錄本次用戶的log,提示用戶【稍後查看,正在發貨中】,後台在峰值過後,啟動非同步補單。需要服務支援冪等。
-
對於發貨的庫存,需要處理熱key。通常的做法是,維護多個key,每個用戶固定去某個查詢庫存。對於大量人搶紅包的場景,可以提前分配。
(5)存儲層
對於業務模型而言,對於DB的要求需要保證幾個原則:
-
可靠性
– 主備:主備能互相切換,一般要求在同城跨機房。
– 異地容災:當一地異常,數據能恢復,異地能選主。
– 數據需要持久化到磁碟,或者更冷的設備。
-
一致性
對於秒殺而言,需要嚴格的一致性,一般要求主備嚴格的一致。
三、微視春節集卡瓜分活動實踐
1. 用戶體驗流程
微視集卡瓜分項目屬於微視春節項目之一。用戶的體驗流程如下:
2. 架構設計圖
微視集卡瓜分項目的架構設計如下圖所示。
-
客戶端主要是微視主APP和H5頁面,主App是入口,H5頁面是集卡活動頁面和瓜分頁面。
-
邏輯部分主要分為:發卡來源、集卡模組、獎品模組,發卡來源主要是任務模組;集卡模組主要由活動模組和集卡模組組成。瓜分部分主要在活動控制層。
-
獎品模組主要是發錢和其他獎品。
3. 瓜分降級預案
為了做好瓜分時刻的高並發,對整個系統需要保證兩個重要的事情:
-
全鏈路梳理,包括調用鏈的合理性和時延設置。
-
降級服務預案分析,提升系統的魯棒性。
針對瓜分全鏈路調用分析時,需要特別說明的幾點:
-
時延很重要,需要全鏈路分析。不但可以提高吞吐量,而且可以快速暴露系統的瓶頸。
-
峰值時刻,補單邏輯需要關閉,避免加劇雪崩。
我們的降級預案大概如下:
(1)一級預案(瓜分時刻前後5分鐘自動進入)
-
入口處1分鐘內陸續放開入口倒計時,未登錄用戶不彈入口。
-
主會場排隊,進主會場20wqps,超過了進入排隊,由接入層頻控控制。
-
拉取資格介面排隊,拉取資格介面20wqps,超過了進入排隊,由接入層頻控控制。
-
搶紅包排隊,搶紅包20wqps,超過了進入排隊,由接入層頻控控制。
-
紅包到賬排隊,如果資格扣除成功,現金髮放失敗,進入排隊,24小時內到賬。非同步補單。
-
入口處調用後端非關鍵rpc:ParticipateStatus,手動關閉。
-
非同步補單邏輯關閉。
(2)二級預案,後端隨機丟請求,接入層頻控失效或者下游服務過載,手動開啟。
(3)三級預案,前端隨機丟請求,後端服務過載或者宕機進入,手動開啟。
綜上,整個瓜分時刻體驗如下所示:
最後,對應漏斗模型,總結下這次活動的實踐。
四、關於架構師成長的幾點思考
-
建立自己關於整個技術領域的知識圖譜很重要,例如從訪問一個網站開始,都經歷了哪些技術點?從工作中學習,對每個技術點刨根問底,把工作中的積累放到自己的知識圖譜中。
-
找機會總結、分享,把知識圖譜分享給別人,一方面可以加深熟悉自己的知識圖譜,另一方面可以和他人技術交流,提高自己分享表達的能力,也是對自身抽象能力的鍛煉。
-
隨著知識圖譜的建立,熟悉互聯網技術的分散式問題解決方案,可以進一步在自己業務上梳理和抽象業務模型,積累自身領域經驗。
-
在業務發展和程式碼重構中,去體驗和驗證自己的領域經驗。再把領域經驗橫向對比其他業務模型。
作者所在的團隊正在招聘後台開發同學,感興趣的同學請在公眾號後台回復「投簡歷」參與應聘~