揭秘:春晚微信紅包,是如何抗住 100 億次請求的?
Hollis的新書限時折扣中,一本深入講解Java基礎的干貨筆記!
從事軟件開發(fā)多年,我偏愛架構設計。無論是電商系統(tǒng)、社交系統(tǒng)還是金融系統(tǒng),我基本都有涉獵。
對于初級工程師而言,最基本的要求是要實現功能,但對于高級工程師和專家工程師而言,更多是要關注架構和性能。
今天,來聊聊紅包問題,你可能疑惑:春晚微信紅包,是如何扛住 100 億次請求的?那么,今天就一起來看看這篇分享。
鏈接:https://www.infoq.cn/article/weixin-bonus-load/?_t=t
今天跟大家分享的主題是如何實現 “有把握” 的春晚搖一搖系統(tǒng)。回憶一下春晚的活動,有什么樣的活動形式呢?
當時我們是直接復用客戶端搖一搖入口,專門給春晚搖一搖定制了一個頁面,可以搖出 “現金拜年”、“紅包”。底下的紅包肯定是大家比較感興趣的,也是今天下午重點介紹的內容。比較精彩的活動背后一定會有一個設計比較獨到的系統(tǒng)。
V0.1 原型系統(tǒng)
我們看一下這個系統(tǒng),我們當時做了一個原型系統(tǒng),比較簡單,它已經實現了所有的功能,搖那個手機的時候會通過客戶端發(fā)出一個請求,接入服務器,然后搖一搖服務,進行等級判斷,判斷以后把結果給到后端,可能搖到拜年或紅包,假設搖到紅包,上面有 LOGO 和背景圖,客戶端把這個 LOGO 和背景圖拉回去,用戶及時拆開紅包,拆的請求會來到紅包系統(tǒng),紅包系統(tǒng)進行處理之后會到支付系統(tǒng),到財富通的轉帳系統(tǒng),最終用戶拿到紅包。拿到錢以后,只是其中一份,還有好幾份是可以分享出去,我們稱之為 “分裂紅包”,通過信息系統(tǒng)轉發(fā)給好友或群里,好友跟群里的人可以再搶一輪。
整個過程歸一下類,叫資源流、信息流、業(yè)務流、資金流,今天講的主要是資源流跟信息流。
原始系統(tǒng)看起來比較簡單,是不是修改一下直接拿到春晚上用就可以了?肯定不行的。到底它有什么樣的問題呢,為什么我們不能用,在回答這個問題之前想請大家看一下我們面臨的挑戰(zhàn)。
1、我們面臨怎樣的挑戰(zhàn)?
第一個挑戰(zhàn)是比較容易想到的,用戶請求量很大,當時預計 7 億觀眾,微信用戶也挺多的,當時預估一下當時峰值達到一千萬每秒,通過圖對比一下,左邊是春運搶火車票,一秒鐘請求的峰值是 12 萬,第二個是微信系統(tǒng),微信系統(tǒng)發(fā)消息有個小高峰,那時候峰值每秒鐘是 33 萬,比較高一點的是預估值一千萬每秒,右邊是春晚時達到的請求峰值是 1400 萬每秒。
這個活動跟春晚是緊密互動的,有很多不確定因素,體現在幾個方面。一個是在開發(fā)過程中,我們的活動怎么配合春晚,一直沒有定下來,很可能持續(xù)到春晚開始前,顯然我們的客戶端跟我們的系統(tǒng)到那時候才發(fā)布出去,這時候我們的開發(fā)就會碰到比較多的問題了,這是第一個。
第二個挑戰(zhàn),在春晚過程中,因為春晚是直播型節(jié)目,節(jié)目有可能會變,時長會變,順序會變,活動過程跟春晚節(jié)目緊密銜接在一起,自己也是會有挑戰(zhàn)的,這也是不確定的因素。再就是我們系統(tǒng)是定制的,專門為春晚定制,只能運行這么一次,這是挺大的挑戰(zhàn),運行一次的系統(tǒng)不能通過很長的時間,檢查它其中有什么問題很難,發(fā)出去了以后那一次要么就成功了,要么就失敗了。
第三個挑戰(zhàn),因為春晚觀眾很多,全國人民都在看,高度關注,我們必須保證成功,萬一搞砸了就搞砸在全國人民面前了。這么大型的活動在業(yè)界少見,缺少經驗,沒有參考的東西。還有就是我們需要做怎樣的準備才能保證萬無一失或者萬有一失,保證絕大部分用的體驗是 OK 的,有很多問題需要我們不斷地摸索思考。原型系統(tǒng)不能再用的,再用可能就掛了。
2、原型系統(tǒng)存在哪些問題?
原型系統(tǒng)有哪些問題呢?第一個是在流量帶寬上,大量的用戶請求會產生大量的帶寬,預估帶寬峰值是 3000pb 每秒,假設我們資源是無限的能夠滿足帶寬需求,也會碰到一個問題,用戶搖到以后有一個等待下載的過程。第二個問題,在接入質量這一塊,我們預估同時在線 3.5 億左右,特別是在外網一旦產生波動的時候怎么保證用戶體驗不受損而系統(tǒng)正常運作。第三個挑戰(zhàn),請求量很大,1000 萬每秒,如何轉到搖一搖服務,搖一搖服務也面臨一千萬請求量,我們系統(tǒng)要同時面對兩個一千萬請求量,這不是靠機器的,大家都有分布式的經驗,這么大請求量的時候任何一點波動都會帶來問題,這是一個很大的挑戰(zhàn)。
3、我們是如何解決這些問題的?
針對以上幾點,我們詳細看一下每一點我們是怎么做到的。我們首先看一下信心指數,把這個系統(tǒng)拿到春晚去跑有多少信心,這里的指數是 10,如果這個系統(tǒng)拿到春晚去用,而且還成功了,這個概率是 10%。當然我們的系統(tǒng)不能建立在運氣的基礎上,應該怎么做?第一個,在帶寬這一塊客戶端可以搖到多種多樣的結果,結果大部分都是靜態(tài)資源,靜態(tài)資源我們可以提前制作出來下發(fā)到客戶端,在后臺做了資源推送的服務,客戶端拿到列表以后可以先行下載,客戶端利用閑時把資源拉過去。碰到幾個問題,資源交付情況的問題,需要增量的發(fā)下去;二是資源更新;三是資源下載失敗,失敗的話怎么辦呢;四是資源覆蓋率,依靠這個系統(tǒng)下載資源的用戶,比如覆蓋率只有 20%、30%,兩個東西就沒有意義了,覆蓋率要達到 90% 左右;五是離線資源下載,萬一有些人把里面的東西修改了,可能會產生意想不到的結果,怎么保證離線資源的安全。
這里有個數據,2 月 9 號到 2 月 18 號下發(fā)資源 65 個,累積流量 3.7PB,峰值流量 1Tb/s。通過這種方式解決了下載資源的問題。
再就是外網接入質量,在上海跟深圳兩地建立了十八個接入集群,每個城市有三網的介入,總共部署了 638 臺接入服務器,可以支持同時 14.6 億的在線。
所有用戶的請求都會進入到接入服務器,我們建立了 18 個接入集群,保證如果一個出現問題的時候用戶可以通過其它的接入,但是在我們內部怎么把請求轉給搖一搖服務,搖一搖處理完還要轉到后端,怎么解決呢?解決這個問題代價非常大,需要很多資源,最終我們選擇把搖一搖服務去掉,把一千萬每秒的請求干掉了,把這個服務挪入到接入服務。除了處理搖一搖請求之外,所有微信收消息和發(fā)消息都需要中轉,因為這個接入服務本身,搖一搖的邏輯,因為時間比較短,如果發(fā)消息也受影響就得不償失了。
恰好有一個好處,我們的接入服務的架構是有利于我們解決這個問題的,在這個接入節(jié)點里分為幾個部分,一個是負責網絡 IO 的,提供長鏈接,用戶可以通過長鏈接發(fā)消息,回頭可以把請求中轉到另外一個模塊,就是接入到邏輯模塊,平時提供轉發(fā)這樣的功能,現在可以把接入邏輯插入。這樣做還不夠,比方說現在做一點修改,還需要上線更新,搖一搖的活動形式沒有怎么確定下來,中間還需要修改,但是上線這個模塊也不大對,我們就把接入的邏輯這一塊再做一次拆分,把邏輯比較固定、比較輕量可以在本地完成的東西,不需要做網絡交互的東西放到了接入服務里。
另外一個涉及到網絡交互的,需要經常變更的,處理起來也比較復雜的,做了個 Agent,通過這種方式基本上實現了讓接入能夠內置搖一搖的邏輯,而且接入服務本身的邏輯性不會受到太大的損傷。解決這個問題之后就解決了接入的穩(wěn)定性問題,后面的問題是搖一搖怎么玩,搖一搖怎么玩是紅包怎么玩,在紅包過程中怎么保證紅包是安全的呢,紅包涉及到錢,錢是不能開玩笑的。第三個問題是怎樣跟春晚保持互動,春晚現場直播,我們怎么跟現場直播掛鉤銜接起來。
先看紅包如何發(fā)放。
前面說道搖一搖請求,其實是在接入服務做的,紅包也是在接入服務里發(fā)出去的,為了在發(fā)紅包過程中不依賴這個系統(tǒng),我們把紅包的種子文件在紅包系統(tǒng)里生成出來,切分,分到每個接入服務器里,每個接入服務器里都部署了專門的紅包文件。一個紅包不能發(fā)兩次,紅包的發(fā)放速率需要考慮,發(fā)放紅包一定有用戶拆,拆了還要再搶,我們需要精確控制,確保所有請求量都是在紅包系統(tǒng)能夠接受的范圍內。在這個過程中還會有另外一個風險,用戶搖到紅包之后還可以有一些分裂紅包分出去,他也可以不分享,不分享的也不會浪費,可以回收過來,會通過本地拉回去。這部分因為是比較少量的,問題不大,因為所有紅包已經發(fā)出去了,只是補充的。這里我們就搞定了紅包發(fā)放。
二是怎么樣保證紅包不被多領或惡意領取,每個客戶領三個紅包,這是要做限制的,但這是有代價的,就是存儲的代價。
我們在我們的協(xié)議里后臺服務接入的搖一搖文件里下發(fā)紅包的時候寫一個用戶領取的情況,客戶端發(fā)再次搖一搖請求的時候帶上來,我們檢查就行了,這是一個小技巧,這種方式解決用戶最多只能領三個、企業(yè)只能領一個限制的問題。這個只能解決正版客戶端的問題,惡意用戶可能不用正版,繞過你的限制,這是有可能的。怎么辦呢?一個辦法是在 Agent 里面,通過檢查本機的數據能夠達到一個目的,搖一搖接入服務例有 638 臺,如果迫到不同的機器,我們是長連,還可以短連,還可以連到另一臺服務器,可以連到不同的地方去。還有一個問題是人海戰(zhàn)術,有些人拿著幾萬、幾十萬的號搶,搶到都是你的,那怎么辦呢?這個沒有太好的辦法,用大數據分析看用戶的行為,你平時養(yǎng)號的嗎,正常養(yǎng)號嗎,都會登記出來。
怎樣跟春晚現場保持互動?需要解決的問題有兩個,一個是要迅速,不能拖太長時間,比如現在是劉德華唱歌,如果給出的明星搖一搖還是上一個節(jié)目不太合適,要求我們配置變更需要迅速,二是可靠。我們怎么做的呢?
春晚現場我們是專門有同學過去的,在他們電腦裝了系統(tǒng),可以跟我們后臺進行交互的,節(jié)目變了節(jié)切一下,變動的請求會發(fā)到后臺,我們部署兩套,一套在深圳、一套在上海,在這個配置里還準備了三步服務,哪一步都可以,同時還可以同步這個數據,這個數據還可以下發(fā)到所有的接入機器,會把它同步過去,不是用一種方式,而是用三種方式,通過這種方式可以迅速的在一千臺服務器成功,是不是能夠達到配置一定能夠用?不一定,春晚現場是不可控的,萬一指令沒有發(fā)出怎么辦?如果六個配置服務都掛了怎么辦,從上一個節(jié)目切到下一個節(jié)目的時候發(fā)生這種問題不是太大,但是主持人在十點三十的時候如果搖紅包一搖啥都沒有,這就怒了,口播出不來也就掛了。
怎么做的呢?主持人肯定有口播,口播的時間點我們大致知道,雖然不知道精確的時間點,比如彩排的時候告訴我們一個時間,后來變了,我們大致知道時間范圍,可以做倒計時的配置,比如十點半不管你有沒有口播我們都要發(fā)紅包了。如果節(jié)目延時太長了,你的紅包十分鐘發(fā)完了,之后搖不到,那也不行,這種情況下我們做了校正,在節(jié)目過程中我們不斷校正倒計時的時間,設了一個策略,定了一個流程,半小時的時候要通知一下我這個時間,因為它是預估的,節(jié)目越到后面能定下來的時間范圍越精確,提前告訴我們,我們就可以調整。那時候現場是在春晚的小會議室,在小會議室看不到現場什么情況,也是通過電視看,結果電視沒信號了,就蒙了,校準就不知道現在怎么回事,進行到哪一步了,當時很著急,還好后來沒事,后續(xù)的幾個節(jié)目還是校正回來了,最終我們是精確的在那個時間點出現了搶紅包。前面講了怎么在系統(tǒng)解決流量的問題、請求量的問題,最重要的一點是我們預估是一千萬每秒,但如果春晚現場出來的是兩千萬、三千萬或四千萬怎么辦,是不是整個系統(tǒng)就掛掉了。
我們就是采用過載保護,過載保護中心點是兩點,前端保護后端,后端拒絕前端。一個是在客戶端埋入一個邏輯,每次搖變成一個請求,搖每十秒鐘或五秒鐘發(fā)送一個請求,這樣可以大幅度降低服務器的壓力,這只會發(fā)生到幾個點,一個是服務訪問不了、服務訪問超時和服務限速。實時計算接入負載,看 CPU 的負載,在銜接點給這臺服務器的用戶返回一個東西,就是你要限速了,你使用哪一檔的限速,通過這種方式,當時有四千萬用戶在搖我們也能扛得住。
V0.5 測試版
這是我們的 0.5 測試版,對這個我們的信心指數是 50,為什么只有 50% 的把握?
我們前面解決的問題都是解決用戶能搖到紅包,服務器還不會壞掉,但是對搖紅包來說那是第一步,后面還有好幾步,還要把紅包拆出來,還要分享,分享完以后其它人可以搶,這個體驗是要保證的,簡單分析一下可以發(fā)現前面是本人操作,后面是好友操作,這里就存在一個契機,你可以做一些服務,一旦出現問題是可以利用的點,可以做延時。剩下的問題是保證本人操作比較好,后面出點問題可以延遲,有延遲表示有時間差處理那個東西。
1、核心體驗是什么?
這里面我們需要確保成功,確保體驗是完全 OK 的,確保成功的時候前面提到原型的系統(tǒng)里解決了搖到紅包的問題,剩下的就是拆紅包和分享紅包。怎么樣確保拆紅包和分享紅包的用戶體驗?
2、如何確保拆 / 分享紅包的用戶體驗?
拆紅包和分享紅包可以做一下切割,可以切割成兩個部分,一個是用戶的操作,點了分享紅包按紐,之后是轉帳,對我們來說確保前面一點就可以了,核心體驗設計的東西再次縮小范圍,確保用戶操作這一步能夠成功。怎么確保呢?我們稱之為 “鐵三角” 的東西,拆 / 分享紅包 = 用戶操作 + 后臺彰武邏輯。這是我們能做到的最高程度了。
3、還能做得更極致嗎?
但我們還可以做的更好一點,前面這個用戶看起來還是成功的,只是入帳入的稍微遲一點點,用戶感覺不到。如果我們異步隊列這里掛了,或者網絡不可用了,概率比較低,我們有三個數據中心,掛掉一個問題不大,萬一真的不能用呢,我們又做了一次異步,分兩部分:一個是業(yè)務邏輯,校驗這個紅包是不是這個用戶的,還有一個透傳隊列,把這個數據再丟到后邊,其實可以相信本機的處理一般是可以成功的,只要做好性能測試基本上是靠譜的。在后面出現問題的時候我們用戶的體驗基本不受損,保證絕大多數用戶的體驗是 OK 的。
V0.8 預覽版
我們又做了 0.8 的版本,預覽版,信心指數 70,我們認為這個東西有七成把握是可以成功的。
大家知道設計并不等于實現,設計的再好,實踐有問題也很崩潰,要保證設計一是全程壓測,二是專題 CODE REVIEW,三是內部演練,四是線上預熱,五是復盤與調整。
復盤包括兩部分,有問題的時候可以把異常問題看出來,二是很正常,跑的時候是不是跟想象的一樣,需要對正常情況下的數據做預估的重新評估,看看是不是符合預期。兩次預熱,一次是搖了 3.1 億次,峰值 5000 萬一分鐘,100 萬每秒,跟我們估算的一千萬每秒差很遠,當時只是針對 iPhone 用戶,放開一個小紅點,你看到的時候可以搶,發(fā)放紅包 5 萬每秒,春晚當晚也是五萬每秒。后面又發(fā)了一次,針對前面幾個問題再做一次。
V1.0 正式版
做完這兩次連接后面就迎接 2 月 18 號春晚的真正考驗。這是 1.0 正式版,信心指數達到 80,我們認為 80% 是可以搞定的。
剩下 20% 在哪里?有 10% 是在現場,現場不可能一帆風順,有可能現場搖的很 High,但后面到處滅火,10% 是在現場處置的時候有比較好的預案和方案能夠解決,另外 10% 是人算不如天算,一個很小的點出現問題導致被放大所有用戶受影響也是有可能的,我們很難控制了。要做出完美無缺的基本不太可能,剩下 10% 就是留運氣。
2 月 18 號跑出來的結果是這樣的,當時搖了 110 億次,峰值是 8.1 億每分鐘,1400 萬每秒。
完
我的新書《深入理解Java核心技術》已經上市了,上市后一直蟬聯(lián)京東暢銷榜中,目前正在6折優(yōu)惠中,想要入手的朋友千萬不要錯過哦~長按二維碼即可購買~
長按掃碼享受6折優(yōu)惠
往期推薦

注意:雪花算法并不是ID的唯一選擇!

Spring Boot 引起的“堆外內存泄漏”排查及經驗總結

看完這妹紙的日更作業(yè),網友直呼:中國計算機界的神!
有道無術,術可成;有術無道,止于術
歡迎大家關注Java之道公眾號
好文章,我在看??
