微信紅包系統(tǒng)設(shè)計分享 | 如何扛住100億次請求?(附PPT下載)
春晚搖一搖活動形式
在了解這個系統(tǒng)之前,先看看羊年春晚有哪些活動形式?春晚搖一搖復用了搖一搖入口,但提供了全新的界面和交互內(nèi)容。
在羊年春晚搖一搖界面里,用戶搖動手機后,可以看到明星拜年、全家福、好友賀卡等精彩紛呈的活動頁;也會有溫馨的“休息一下”,或讓很多誤以為中獎的“掛服務器”等特殊用途的頁面。
大家最期待的肯定是搖紅包,搖中紅包的幸運用戶除了自己領(lǐng)到一份紅包(種子紅包)外,還可以領(lǐng)到若干份用于分享給其他好友的紅包(分裂紅包)。
圍繞這些活動,下面將會通過4個處于項目不同階段的里程碑版本來介紹我們設(shè)計、實現(xiàn)這一系統(tǒng)過程中的一些思考和做法,特別是標題里提到的“有把握”是由何而來。
V0.1原型系統(tǒng)
原型系統(tǒng)很簡單,但已經(jīng)基本實現(xiàn)了春晚搖一搖的需求。原型系統(tǒng)的架構(gòu)見下圖。
相關(guān)的處理流程如下:
- 用戶搖動手機后,客戶端產(chǎn)生搖一搖請求,請求發(fā)到接入服務后,會被轉(zhuǎn)發(fā)到搖一搖服務;
- 搖一搖服務會根據(jù)現(xiàn)場節(jié)目的流程,經(jīng)過一系列的邏輯判斷,給客戶端返回一個結(jié)果:明星拜年、紅包或者其他活動;
- 假設(shè)是搖到了紅包,由于紅包都是企業(yè)贊助的,需要對企業(yè)形象進行展示,客戶端會從CDN拉回這個企業(yè)的LOGO等資源,最終展示出一個完整的紅包;
- 隨后用戶拆紅包時,請求會進入紅包系統(tǒng),再到支付系統(tǒng),最后到財付通系統(tǒng)完成一系列復雜的賬務處理,最終拿到紅包;
- 用戶還可以分享紅包,被分享的紅包通過消息系統(tǒng)發(fā)給好友或群,其他人可以再搶一輪;在這一過程中,安全系統(tǒng)保障紅包活動的業(yè)務安全。
- 上述數(shù)據(jù)的流動可以分下類:資源流、信息流、業(yè)務流和資金流。本文將主要聚焦在資源流和信息流。
面臨的挑戰(zhàn)
原型系統(tǒng)看起來已經(jīng)足夠簡單,功能也基本完備,是不是可以稍加修改后直接用在春晚現(xiàn)場呢?答案肯定是不行。那么問題來了:為什么不行?
回答這一問題前,我們先看一下看似簡單的活動背后,面臨著哪些挑戰(zhàn)?
海量用戶請求,預計請求峰值1000萬/秒
1000萬/秒究竟是多大的規(guī)模,可以通過下圖更直觀地感受下:
注:搶火車票數(shù)據(jù)引用自公開數(shù)據(jù)
春晚全程互動,不確定因素多
這個系統(tǒng)需要跟羊年春晚全程緊密互動,從項目開始到結(jié)束,有一系列的不確定因素會加大系統(tǒng)實現(xiàn)的復雜度:在開發(fā)階段,針對節(jié)目與活動形式如何配合這個問題的討論有可能持續(xù)到春晚前,如何使系統(tǒng)能服務多變的需求?在春晚現(xiàn)場,節(jié)目數(shù)量多,節(jié)目時長甚至順序都有可能調(diào)整,如何做到現(xiàn)場節(jié)目與搖一搖活動無縫銜接?
系統(tǒng)深度定制,成敗在此一舉
作為專為春晚設(shè)計的系統(tǒng),部署上線后真正能運行的時間就只有幾個小時,這幾個小時內(nèi),常規(guī)系統(tǒng)所提倡的灰度發(fā)布、先扛住再優(yōu)化等做法并不是太適用。在這短暫的時間內(nèi),只有一次機會:要么成功,要么失敗。
全民高度關(guān)注,必須成功
春晚會有7億左右的觀眾,大家對這一活動抱有很大期望,全民矚目之下,只能成功,不能失敗。
l缺少歷史經(jīng)驗,把握不大
如此大型的活動,對我們而言是史無前例的,并沒有太大的信心。前邊提到的1000萬/秒的峰值是如何估算出來?各個環(huán)節(jié)會有多少用戶參與?系統(tǒng)需要預留多少資源?這些問題不會有現(xiàn)成的答案,都需要摸索與思考。
可見,在看似簡單的活動背后,隱藏了巨大的挑戰(zhàn),之前假設(shè)的原型系統(tǒng)不太可能勝任,需要做更深入的優(yōu)化。
需要優(yōu)化哪些環(huán)節(jié)?比較顯而易見的有三個:
流量帶寬
春晚搖一搖需要用到大量的多媒體資源,這些資源都需要從CDN下載。經(jīng)過評估,帶寬峰值需求是3Tb/s,會帶來巨大的帶寬壓力。即使我們有無限的資源,帶寬需求能被滿足,客戶端在搖一搖后下載資源所需的等待時間也會帶來很大的用戶體驗損害,是不可接受的。
接入質(zhì)量
接入是后臺系統(tǒng)的第一道關(guān),所有請求都會到達接入。預計當晚會有3.5億的在線,如何盡可能保障外網(wǎng)接入質(zhì)量?甚至在外網(wǎng)波動時也不受太大影響?
海量請求
1000萬/秒的請求從外網(wǎng)涌進來后,都被路由給搖一搖服務,也就是說搖一搖服務也將有1000萬/秒的請求量。這意味著需要確保系統(tǒng)內(nèi)2個1000萬/秒的高可用,在分布式系統(tǒng)內(nèi),這是個挺大的問題。
如果要對系統(tǒng)能否最終取得成功量化一個信心指數(shù)的話,這個原型系統(tǒng)的信心指數(shù)是10。這個數(shù)字表示如果春晚搖一搖采用這套系統(tǒng)并取得成功,我們認為90%是靠運氣。也可以換種說法:拿這個系統(tǒng)到春晚搖一搖,90%的可能會掛掉。
系統(tǒng)肯定不能以運氣為基礎(chǔ),這幾個問題如何解決?
V0.5?測試版
V0.5的目標就是為了解決V0.1原型系統(tǒng)里的幾個問題。
資源預下載
春晚使用的資源比較多,也比較大,但基本都是靜態(tài)資源,是可以提前幾天下載到客戶端的。保存到本地后,在需要使用的時候,客戶端直接從本地加載,從而省去了集中在線下載所需的帶寬需求,另外用戶搖一搖時不再需要下載資源,可以有更好的用戶體驗。下圖展示了資源預下載過程。
資源推送模塊負責將資源上傳到CDN,同時推送資源列表給客戶端。推送過程基于微信消息系統(tǒng)實現(xiàn),可以在極短時間內(nèi)把資源列表推送給幾億的用戶。
資源預下載需要解決以下幾個問題:
- 資源交付情況
- 資源更新
- 資源下載失敗
- 資源覆蓋率
- 離線資源安全
通過這套資源預下載系統(tǒng),2015.2.9 – 2015.2.18?期間,下發(fā)了資源65個,累計流量3.7PB,其中閑時峰值達到1Tb/s。
外網(wǎng)接入梳理
要保證接入質(zhì)量,除了需要保證接入服務本身的穩(wěn)定性外,需要做到:
- 具備在某些外網(wǎng)接入出現(xiàn)波動的時候,能自動切換到正常接入服務的能力;
- 保障網(wǎng)絡(luò)與服務具備足夠的冗余容量。
微信客戶端已經(jīng)具備了外網(wǎng)自動容災切換的能力,下邊再看一下系統(tǒng)的外網(wǎng)部署情況。
我們重新梳理了外網(wǎng)的部署,最終在上海IDC和深圳IDC各設(shè)置了9個TGW接入集群。每個IDC都在3個不同的園區(qū)分別部署了電信、移動和聯(lián)通的外網(wǎng)接入線路。
另外,接入服務也進行了臨時擴充,兩地共有638臺接入服務器,最多支持14.6億的同時在線。
接入服務內(nèi)置“搖一搖”
4.3.1.?架構(gòu)變動
前面提到,系統(tǒng)需要面對預計1000萬/秒從外網(wǎng)的請求,同時還需要在內(nèi)網(wǎng)轉(zhuǎn)發(fā)同樣是1000萬/秒的請求給搖一搖服務,除此之外,還需要在各種異常情況下確保高可用。在如此海量請求之下,在這個分布式系統(tǒng)中,任何一點網(wǎng)絡(luò)或服務的波動都可能是災難性的,這里邊的困難程度可想而知。
正面解決這一問題的成本過高,我們選擇了去掉搖一搖服務——把搖一搖邏輯集成到了接入服務,從而去掉了1000萬/秒的轉(zhuǎn)發(fā)請求。
但這樣做,有一個前提:不能降低接入服務的穩(wěn)定性。因為不單是春晚搖一搖請求,微信消息收發(fā)等基礎(chǔ)功能的請求也需要通過接入服務來中轉(zhuǎn),假如嵌入的搖一搖邏輯把接入服務拖垮,將得不償失。
接入服務的架構(gòu)剛好有助于解決這個問題。
如上圖所示,接入服務有一個網(wǎng)絡(luò)IO模塊,這個模塊維護了來自客戶端的TCP連接,收發(fā)數(shù)據(jù),負責跟客戶端通訊。網(wǎng)絡(luò)IO模塊是作為獨立的進程組運作的,收到的請求通過本機共享內(nèi)存發(fā)給接入邏輯模塊處理。接入邏輯模塊也是一組獨立運行的進程,通常情況下是由請求中轉(zhuǎn)邏輯通過RPC把請求轉(zhuǎn)發(fā)給其他邏輯服務器處理?,F(xiàn)在搖一搖邏輯作為嵌入邏輯,整合到了接入邏輯模塊。由于網(wǎng)絡(luò)IO模塊與接入邏輯模塊相互隔離,可以單獨對接入邏輯模塊進行升級,不會影響到已有的網(wǎng)絡(luò)連接,這大大降低了嵌入邏輯帶來的風險。
但這樣還不夠,還可以把嵌入到接入邏輯模塊里的搖一搖邏輯盡可能簡化,只保留比較簡單、穩(wěn)定、只需要單機計算即可完成的輕量邏輯;把其他較復雜、可能需要經(jīng)常變更、或需要跨機訪問的邏輯獨立為搖一搖agent,作為獨立運行的進程,通過本機共享內(nèi)存與嵌入搖一搖邏輯通訊。
4.3.2.?搖一搖邏輯實現(xiàn)
接入服務架構(gòu)的修改使得內(nèi)置搖一搖邏輯變得可能,剩下的就是怎樣實現(xiàn)春晚搖一搖邏輯?春晚搖一搖邏輯最重要的是搖紅包,搖紅包則需要重點解決以下問題:
紅包如何發(fā)放?
所有紅包都源自紅包系統(tǒng),但為了在運行時不依賴紅包系統(tǒng),紅包系統(tǒng)生成的種子紅包文件被提前部署到了接入服務。為確保紅包文件不會被重復發(fā)放,有個文件切分程序完成不同機器的文件切分,每臺機只保留自己需要處理的那部分紅包;另外,為了確保紅包不漏,還有另一個程序完成所有機器紅包文件的合并校驗。
搖到紅包的用戶如果選擇不分享紅包,這些紅包會被紅包系統(tǒng)回收,一部分作為種子紅包經(jīng)由搖一搖agent回流到接入服務進行發(fā)放。
搖一搖agent會根據(jù)預設(shè)的策略給內(nèi)置的搖一搖邏輯提供可下發(fā)的種子紅包。紅包是每秒勻速下發(fā)的,可以精確控制全局紅包下發(fā)速度,保持在紅包/支付系統(tǒng)能正常處理的范圍之內(nèi)。
怎樣保障安全?
單用戶紅包個數(shù)限制
業(yè)務要求每個用戶最多可以領(lǐng)取3個紅包,并且每個贊助商最多1個。常規(guī)實現(xiàn)里,需要在后臺存儲用戶領(lǐng)取記錄,每次搖一搖請求時取出來計算,如果拿到紅包還需要更新存儲。但這里增加了對存儲的依賴,海量請求下,穩(wěn)定性不易保障。我們借鑒了HTTP協(xié)議的COOKIE,在搖一搖協(xié)議里也實現(xiàn)了類似的機制:后臺可以寫入用戶的紅包領(lǐng)取情況到COOKIE,交由客戶端保存,客戶端在下次請求時帶上來,服務器再取出來判斷。這就無需后臺存儲也可以實現(xiàn)同樣的目的。
破解協(xié)議的惡意用戶
協(xié)議總是有可能被破解的,惡意用戶可以制作自動機,繞開COOKIE檢測機制。所以COOKIE檢測機制只能用于絕大部分使用正??蛻舳说挠脩?。對于破解協(xié)議的惡意用戶可以通過在本機存儲紅包下發(fā)記錄來打擊。
游擊戰(zhàn)
雖然接入服務使用長連接,但惡意用戶可以不斷重連,變換不同的服務器來獲取紅包,針對這種情況,我們設(shè)計了紅包發(fā)放匯總服務,可以在所有接入服務上同步已經(jīng)達到紅包領(lǐng)取上限的用戶。
以上策略依次遞進,后一步較前一步更深入一層解決問題,但是在設(shè)計上,前一步并不依賴后一步,即使后邊的步驟出現(xiàn)故障無法按預期進行,也不會影響前邊的結(jié)果,在最差的情況下,系統(tǒng)仍然可以保證單用戶紅包個數(shù)限制的需求。
如何與春晚現(xiàn)場同步互動?
春晚搖一搖系統(tǒng)需要配合春晚現(xiàn)場節(jié)目進行互動,春晚切換節(jié)目或者主持人進行活動的口播時,系統(tǒng)都需要同步切換活動配置。
這里一是要求快速,二是要求穩(wěn)定。為此我們設(shè)計了這樣一個配置系統(tǒng)。
春晚現(xiàn)場有一個配置前臺,現(xiàn)場人員可以通過這個配置前臺發(fā)送變更指令到后臺。后臺有上海和深圳兩個接收點,每個接收點由處于不同園區(qū)的3組冗余的配置服務構(gòu)成。配置服務接收到配置后會同步到另一接收點,同時以文件形式下發(fā)到所有接入服務。為確保同步成功,使用了RPC/RSYNC/變更系統(tǒng)三個冗余變更通道來同時變更配置。從配置前臺發(fā)起變更,到接入服務加載配置,全程可以在10秒內(nèi)完成。
看起來快速和穩(wěn)定都滿足了,是不是就已經(jīng)足夠了?請思考以下異常場景:
- 春晚前臺無法工作或網(wǎng)絡(luò)故障,指令無法發(fā)給配置服務;
- 所有配置服務均無法工作或網(wǎng)絡(luò)故障,配置無法同步給接入服務。
這些異常在春晚節(jié)目過程中臨時出現(xiàn)的話,一般情況下影響并不大,我們可以臨時手工變更配置,贏得足夠時間去修復系統(tǒng)。但是,如果此時主持人正在號召大家拿起手機搶紅包,我們是沒有足夠的把握可以在極短時間內(nèi)完成全系統(tǒng)的配置變更的,也就是說極有可能功虧一簣,關(guān)鍵配置變更不了,紅包根本出不來。還有一種類似的場景,就是搶紅包開始后,也因為配置變更問題,結(jié)束不了,沒法切回其他活動,損壞用戶體驗。
針對口播搶紅包這個關(guān)鍵點,我們采用這樣的配置變更策略:使用搶紅包倒計時配置,到點后自動開始搶紅包時段,經(jīng)過預設(shè)的時間后,又自動結(jié)束。另外,由于春晚節(jié)目的口播時間點具有不確定性,我們制定了變更策略,在節(jié)目過程中可以逐步校正倒計時。于是這一關(guān)鍵配置就只與時間相關(guān),機器時間相對容易保障,通過NTP就可以達到足夠精度的時間同步,我們還對機器時間進行集中監(jiān)控,可以發(fā)現(xiàn)并處理機器時間出現(xiàn)異常的機器。
預估帶來的問題
至此,V0.1原型系統(tǒng)前邊提到的三個問題均已解決,1000萬/秒的海量請求可以扛住。但是,1000萬/秒是預估的,如果最終來了2000萬怎么辦?4000萬呢?看起來數(shù)字有點不可思議,但真有1億甚至幾億用戶在不停的搖,也還是有可能出現(xiàn)的。
對于2000萬/秒,我們其實并不擔心,接入服務經(jīng)過不斷的優(yōu)化,可以在提供容災冗余的基礎(chǔ)上,仍有2500萬/秒的吞吐能力。
但是4000萬/秒大大超出了后臺服務能力,怎么辦?
海量服務之道有個過載保護,如果沒法硬扛,可以做到自我保護。簡單的說就是前端保護后端,后端拒絕前端。
客戶端在服務訪問不了、服務訪問超時和服務限速時主動減少請求。
接入服務可以在發(fā)現(xiàn)某個客戶端請求過于頻繁時,會自動延遲回包,間接達到拉大請求間隔的效果,最終實現(xiàn)在后臺把客戶端請求頻率限制在合理范圍內(nèi);另外,接入服務會計算機器的CPU使用情況,CPU使用率到達不同預設(shè)閾值時,會自動返回不同檔次的限速給客戶端,通過客戶端配合完成限速。
通過這些措施,在請求量超預期時,系統(tǒng)會自動降級,從而實現(xiàn)自保。
綜上,可以得到V0.5測試版的架構(gòu),信心指數(shù)50。
V0.8?預覽版
核心體驗是什么?
為什么V0.5測試版的信心指數(shù)只有50?還有哪些沒做到位?
反思一下,可以發(fā)現(xiàn):V0.5測試版主要聚焦于如何處理海量的搖一搖請求,讓用戶可以愉快的搖出紅包,那搖出紅包之后呢?V0.5測試版并未對這個問題作進一步的思考。
先看一下?lián)u一搖的核心體驗——搖紅包,搖紅包涉及搖到紅包、拆紅包、分享紅包、好友搶紅包等等步驟。
稍加分析即可發(fā)現(xiàn),前三步是本人操作,后續(xù)是好友操作。從本人操作到好友操作之間是有一定時延的,這也就意味著這里其實可以接受一定程度的有損體驗——延時。
V0.5測試版已經(jīng)解決搖紅包的問題,剩下就看拆紅包和分享紅包了。
如何確保拆紅包和分享紅包的用戶體驗?
可以把拆紅包和分享紅包抽象一下,它們都是由兩個部分組成:用戶操作(信息流)和后臺的紅包處理邏輯(業(yè)務流)。對用戶來說,他關(guān)心的是操作是否成功,而不是后臺的紅包處理邏輯。因此這個問題可以進一步簡化為:如何確保拆紅包和分享紅包的用戶操作能成功?
我們在用戶操作和紅包處理邏輯之間加入了一個中間層。這個中間層包括紅包簡化邏輯和紅包異步隊列,實現(xiàn)了信息流和業(yè)務流的異步化和解耦。
紅包簡化邏輯
通過一些算法設(shè)計,紅包簡化邏輯可以通過本地計算完成對紅包請求是否合法的初步判斷,合法請求放入異步隊列,然后就可以返回客戶端處理成功;
紅包異步隊列
紅包異步隊列存儲來自簡化邏輯的請求。在存儲上,異步隊列使用3機方案,3機寫2份成功即算入隊成功。異步隊列的處理邏輯會從隊列取出請求繼續(xù)發(fā)起對紅包系統(tǒng)的調(diào)用,完成后續(xù)的紅包邏輯。在紅包系統(tǒng)故障時,會有妥善的重試策略,確保在系統(tǒng)恢復后重試成功。
接入服務、紅包簡化邏輯服務、紅包異步隊列構(gòu)成了所謂的“鐵三角”,可以在紅包系統(tǒng)出現(xiàn)嚴重問題時,保護用戶體驗在較長時間內(nèi)基本不受損,爭取到修復故障的寶貴時間。
其實再仔細思考一下,“鐵三角”還可以做得更強:把紅包簡化邏輯再次拆分為基本的業(yè)務邏輯和本地透傳隊列。業(yè)務邏輯完成紅包合法性校驗后,把請求寫入本地文件隊列,本地文件隊列再透傳給紅包異步隊列完成后續(xù)處理。這樣即使紅包異步隊列出現(xiàn)意外抖動,也不會影響到用戶操作結(jié)果。
V0.8預覽版已經(jīng)基本成型,信心指數(shù)達到70。
V1.0?正式版
大家知道設(shè)計≠實現(xiàn),為保證最終實現(xiàn)和線上系統(tǒng)運作符合設(shè)計預期,我們還做了:
全程壓測
未經(jīng)壓測的系統(tǒng)是很危險的,無法真正了解系統(tǒng)在壓力下的表現(xiàn)是否符合預期?系統(tǒng)的極限在哪?為此,我們建立一個壓測環(huán)境,對系統(tǒng)進行不間斷的壓測。系統(tǒng)部署后,在現(xiàn)網(wǎng)環(huán)境也進行了多輪真實壓測。
專題CODE REVIEW
多部門聯(lián)合做了專題CODE REVIEW,在代碼層面對關(guān)鍵路徑做了仔細的評估。
內(nèi)部演練
客戶端發(fā)布流程較長,全面鋪開版本需要更長的時間,做不到像服務器一樣可以迅速上線fix問題。因此在發(fā)布客戶端前,除了測試外,一次次的真實演練是非常必要的。
線上預熱
在2015.2.12和2015.2.15,最終爭取到了兩次預熱的機會,對系統(tǒng)進行了實戰(zhàn)驗證。
因為預熱規(guī)模的原因,搖一搖峰值并未達到預估值。但發(fā)放紅包的速率一直維持在5萬/秒的預設(shè)值,對后端“鐵三角”和其后的紅包系統(tǒng)進行了充分的檢驗。
復盤與調(diào)整
每次演練和預熱都是難得的機會,不僅那些出異常的模塊,那些看起來表現(xiàn)正常的模塊,也可以通過復盤和推演,確認是否完全符合預期,挖掘出可能的隱患點,進而解決。
最終,我們發(fā)布了V1.0正式版。
V1.0正式版架構(gòu)上與V0.8預覽版并無不同,但是信心指數(shù)加到了80。
我們認為剩下的20%里,有10%體現(xiàn)在對突發(fā)狀況的預案與現(xiàn)場處置。系統(tǒng)如此龐大與復雜,是不是還有沒想到、未暴露出來、還做得不夠或者在有限資源內(nèi)無法解決的問題?這些問題一旦如果出現(xiàn)了,是不是有可能最終左右了整個局面?所以最后的10%就是靠運氣,別出現(xiàn)這些問題。
后記
2015.2.18?羊年春晚搖一搖
- 全程搖動110億次;
- 峰值8.1億/分鐘,1400萬/秒。
本文PPT下載:
鏈接: http://pan.baidu.com/s/1qW5VkPA 密碼: 4p7x
作者:張文瑞 iotazhang ?騰訊 WXG 技術(shù)架構(gòu)部
來源:36大數(shù)據(jù)
原文地址:http://www.36dsj.com/archives/36513
不錯,十分專業(yè)
干貨 ?
感覺好牛逼,雖然看不懂技術(shù) ??
好贊 好專業(yè) 需要多學習才能看懂