本文為CSDN的《程序員》雜志原創文章,下文有修訂和改動”。
1、引言
南方企業一直有過年找老板“逗利是”的習俗,每年春節后開工的第一天,騰訊大廈都會排上長長的隊伍,集體上樓找老板們領紅包。按照廣東習俗,已經結婚的同事也要給未婚同事發紅包,這一天騰訊員工就在春茗和尋找紅包中度過。
由此孵化了一個內部項目,通過微信來收發紅包,把這個公司全員娛樂活動與最活躍的IM平臺微信結合起來。最初這個項目并沒有預期對外,但是入口不小心開放后,成為了現象級產品。2014年開始爆發性增長,每年的發放量都是上一年的若干倍。根據騰訊公布的數據,到2016年春節,已經是每秒十萬次支付,每天近十億訂單的系統。
微信紅包本質是小額資金在用戶帳戶流轉,有發、搶、拆三大步驟。在這個過程中對事務有高要求,所以訂單最終要基于傳統的RDBMS,這方面是它的強項,最終訂單的存儲使用互聯網行業最通用的MySQL數據庫。支持事務、成熟穩定,我們的團隊在MySQL上有長期技術積累。但是傳統數據庫的擴展性有局限,需要通過架構解決。
補充說明:本文對應的演講PPT詳見《微信紅包數據架構演變(PPT) [附件下載]》。
技術交流:
二、分享者

莫曉東:微信支付高級DBA,擁有豐富的數據架構和運維實戰經驗,擅長大規模MySQL數據庫集群的架構、優化和高可用。2010年起在騰訊從事DBA工作,目前專注于微信社交支付的存儲層運維和架構優化。
三、系列文章
? 系列文章目錄:
《社交軟件紅包技術解密(一):全面解密QQ紅包技術方案——架構、技術實現等》
《社交軟件紅包技術解密(二):解密微信搖一搖紅包從0到1的技術演進》
《社交軟件紅包技術解密(三):微信搖一搖紅包雨背后的技術細節》
《社交軟件紅包技術解密(四):微信紅包系統是如何應對高并發的》
《社交軟件紅包技術解密(五):微信紅包系統是如何實現高可用性的》
《社交軟件紅包技術解密(六):微信紅包系統的存儲層架構演進實踐》(* 本文)
《社交軟件紅包技術解密(七):支付寶紅包的海量高并發技術實踐》
《社交軟件紅包技術解密(八):全面解密微博紅包技術方案》
《社交軟件紅包技術解密(九):談談手Q春節紅包的設計、容災、運維、架構等》
《社交軟件紅包技術解密(十):手Q客戶端針對2020年春節紅包的技術實踐》
《社交軟件紅包技術解密(十一):最全解密微信紅包隨機算法(含演示代碼)》
《社交軟件紅包技術解密(十二):解密抖音春節紅包背后的技術設計與實踐》
《社交軟件紅包技術解密(十三):微信團隊首次揭秘微信紅包算法,為何你搶到的是0.01元》
? 其它相關文章:
《技術往事:“QQ群”和“微信紅包”是怎么來的?》
《QQ 18年:解密8億月活的QQ后臺服務接口隔離技術》
《月活8.89億的超級IM微信是如何進行Android端兼容測試的》
《開源libco庫:單機千萬連接、支撐微信8億用戶的后臺框架基石 [源碼下載]》
《微信技術總監談架構:微信之道——大道至簡(演講全文)》
《微信技術總監談架構:微信之道——大道至簡(PPT講稿) [附件下載]》
《如何解讀《微信技術總監談架構:微信之道——大道至簡》》
《微信海量用戶背后的后臺系統存儲架構(視頻+PPT) [附件下載]》
《微信異步化改造實踐:8億月活、單機千萬連接背后的后臺解決方案》
《微信朋友圈海量技術之道PPT [附件下載]》
《架構之道:3個程序員成就微信朋友圈日均10億發布量[有視頻]》
《快速裂變:見證微信強大后臺架構從0到1的演進歷程(一)》
《快速裂變:見證微信強大后臺架構從0到1的演進歷程(二)》
《微信“紅包照片”背后的技術難題》
《微信技術分享:微信的海量IM聊天消息序列號生成實踐(算法原理篇)》
《微信技術分享:微信的海量IM聊天消息序列號生成實踐(容災方案篇)》
4、前端流量控制
發十億紅包,難在哪里?
- 1)大量用戶在同一時間發搶紅包,瞬間產生每秒數萬次的請求,除夕可能成百千萬次;
- 2)這個量級的請求如果不加以疏導處理直接到達后臺,必定會導致后端服務過載甚至崩潰。
主要思路是縮短關鍵業務流程,分離可以通過異步、緩存等方式解決的問題,減輕系統壓力,加快響應速度,在存儲層前面建上一座大壩。
CGI無狀態:
接入層無狀態,邏輯層也無狀態,可以方便地水平擴展。但依賴MySQL事務保證交易完整,保證紅包系統的精簡,減少瓶頸的存在。
資源靜態化:
利用騰訊強大的基礎資源優化部署,盡量把動態內容轉為靜態資源。靜態資源和CGI分離,靜態資源通過CDN就近接入,減少用戶和CGI的交互,減少內網、訪問延時和數據請求。
業務流程異步化:
微信紅包的發、搶、拆背后都有多個內部環境,關鍵流程精簡,非關鍵流程和后續業務邏輯進入異步隊列進行處理,減少了用戶的等待時間,也極大降低了峰值雪崩的概率。繁多的非關鍵鏈路也不會影響到主流程。
過載保護:
前端保護后端,能在前端處理,就不傳遞到后端:
- 1)前端需要按后端能力做削峰限流;
- 2)客戶端、接入層、邏輯層逐層控制流量;
- 3)前端更容易容錯處理,全力保護存儲層。
微信的過載保護在客戶端已提前預埋了策略,在連接失敗或超時情況下會有相應提示,減少用戶重復請求次數。接入層針對頻繁發出請求的客戶端限制響應速度,并對系統負載劃分出若干等級,達到不同閾值時引導客戶端使用不同限速速率;在異常情況出現時,異步限流降速減輕服務器端壓力防止過載。
多級讀緩存:
發一個群紅包,搶紅包的請求量遠大于發紅包,如果已經領過完全可以拒絕。邏輯層增加緩存,類似可以緩存的請求都緩存起來,進一步減少存儲層流量。
訂單寫緩存:
訂單系統有很多請求不會真正完成全流量,創建這些廢單不但浪費存儲資源,還會擠占邏輯層和數據層的處理能力,影響其他交易。訂單在完成支付前可以先落在緩存中,完成支付后再持久化。
5、存儲層的高可用設計
在數百倍千倍的業務增長下,存儲層很難簡單無限擴容,一方面設備成倍增加的成本巨大,另一方面存儲層瓶頸堆積不一定能解決問題。
讀寫分離:
寫請求需要在主機上,實時讀也需要走主機。有大量對延時不那么敏感,又影響性能的查詢,完全可以放到從機。讀寫分離策略是MySQL分布式的入門,簡潔地提高了系統容量。
水平切分:
數據的水平切分,實質就是分庫分表;選取一張數據表按照主要緯度把數據拆分開。實現存儲層的平行擴展。有效降低了單臺數據庫機器的負載,也減小了服務不可用的可能性。單臺數據庫宕機只會導致部分數據不能訪問。主要需要考慮路由規則的選定,方便擴縮容以及數據的均衡分布。
垂直切分:
數據表除了水平切分,行內數據可以按屬性進一步分開。核心表只保留最關鍵的字段,保證數據文件短小緊湊。以紅包為例,昵稱和祝福語這類較長的信息,不屬于核心數據,完全可以切分到別的機器上,進一步提升核心數據庫的容量。不同數據適合的存儲類型也不一樣,這類重復率高的長字符串更適合NoSQL存儲,對存儲空間和性能都是節約極大。
空間換時間:
按不同維度組織表,比如按訂單屬性和用戶屬性進行組織;適應不同的請求場景,避免復雜的查詢。不同維度的表可以通過對賬對齊,非核心表可以適當冗余,減少多次請求。
鎖的優化:
多人爭搶紅包通過數據庫事物來保證,必然存在競爭MySQL行鎖。核心事物必須盡量精簡,避免死鎖。同一個訂單的所有請求,盡量在邏輯層進程預排隊后通過一個連接發送請求到數據庫。
冷熱分離:
核心數據庫存放高頻數據,其他數據可以定時移到成本低的冷數據庫中。這樣可以為核心數據庫使用最好的SSD設備,快速設備容量較小較貴,不可能在全量數據上使用。同時可以保證數據表的容量不會一直積累,大表也會導致性能下降。
6、異地多活
當系統足夠大時,就必須開始考慮異地部署的問題,讓數據盡可能離用戶更近。而且進一步的高可用不能局限在同一地域,必須跨數據中心跨城多活才能抵御系統性風險。因為跨城的幾十毫秒延時,微信紅包的異地活動設計為多數據中心相互獨立。非災難灰度不會將其他數據中心的數據導入到線上。
就近接入:
以微信紅包系統的異步部署為例,第一個好處是用戶就近接入,減少跨城的穿越流量。根據發送者的地域標志數據落地到不同數據中心,在不同地域實現業務閉環。
數據分離:
當前的網絡技術限制,使用光纖也無法保證跨城數據的同步延時問題。所以微信紅包的跨城數據中心并不進行數據實時同步。不同區域各自承載業務流量,地域上實現平衡,各地的訂單數據各自獨立存儲。
異地容災:
如果出現地域性故障,我們需要有機制去保證服務可用性。有了異步部署,假如深圳出現系統性故障,那么我們可以直接把請求接入上海。各數據中心獨立部署,如果某地系統達到最大容量,可以進行跨地域分流。
7、有損服務和柔性降級
我們遇到最多的問題就是海量請求,通過分布式系統來實現海量請求,根據CAP理論不能同時保證一致性和高可用,必須有取舍。我們首先保證可用性,同時實現最終一致性。有以下原則。
有損服務:
要追求高可用性,可以犧牲部分數據一致性和完整性從而保證核心功能。在資源一定的前提下,滿足用戶的核心需求。微信紅包的核心點是搶、拆紅包,系統必須盡最大可能保證核心步驟流暢,但在瓶頸時立即降級防止引起系統雪崩。但是要保證數據能最終對齊,金融屬性的系統數據安全硬要求。
柔性可用:
柔性可用是在有損服務價值觀支持下的方法,結合具體場景提供不同級別的用戶體驗,保證盡可能成功返回關鍵數據。把握用戶在每一個場景中的核心需求,設計不同層次滿足核心訴求的辦法。系統首先要實現容災和自動切換;其次邏輯資源應該隔離;服務過載時必須自動快速拒絕。
8、結束語
本文簡單介紹了微信紅包的存儲層服務設計準則,在業務從起步到小跑再到騰飛的過程中,背后的海量服務能力將對其最終成敗有著越來越深遠的影響。在互聯網爆發性增長中,海量服務能力決定項目成敗,必須在項目初期就做好海量服務的準備。
附錄1:有關微信、QQ的文章匯總
《微信朋友圈千億訪問量背后的技術挑戰和實踐總結》
《騰訊技術分享:騰訊是如何大幅降低帶寬和網絡流量的(圖片壓縮篇)》
《騰訊技術分享:騰訊是如何大幅降低帶寬和網絡流量的(音視頻技術篇)》
《微信團隊分享:微信移動端的全文檢索多音字問題解決方案》
《騰訊技術分享:Android版手機QQ的緩存監控與優化實踐》
《微信團隊分享:iOS版微信的高性能通用key-value組件技術實踐》
《微信團隊分享:iOS版微信是如何防止特殊字符導致的炸群、APP崩潰的?》
《騰訊技術分享:Android手Q的線程死鎖監控系統技術實踐》
《微信團隊原創分享:iOS版微信的內存監控系統技術實踐》
《讓互聯網更快:新一代QUIC協議在騰訊的技術實踐分享》
《iOS后臺喚醒實戰:微信收款到賬語音提醒技術總結》
《騰訊技術分享:社交網絡圖片的帶寬壓縮技術演進之路》
《微信團隊分享:視頻圖像的超分辨率技術原理和應用場景》
《微信團隊分享:微信每日億次實時音視頻聊天背后的技術解密》
《QQ音樂團隊分享:Android中的圖片壓縮技術詳解(上篇)》
《QQ音樂團隊分享:Android中的圖片壓縮技術詳解(下篇)》
《騰訊團隊分享:手機QQ中的人臉識別酷炫動畫效果實現詳解》
《騰訊團隊分享 :一次手Q聊天界面中圖片顯示bug的追蹤過程分享》
《微信團隊分享:微信Android版小視頻編碼填過的那些坑》
《微信手機端的本地數據全文檢索優化之路》
《企業微信客戶端中組織架構數據的同步更新方案優化實戰》
《微信團隊披露:微信界面卡死超級bug“15。。。。”的來龍去脈》
《QQ 18年:解密8億月活的QQ后臺服務接口隔離技術》
《月活8.89億的超級IM微信是如何進行Android端兼容測試的》
《以手機QQ為例探討移動端IM中的“輕應用”》
《一篇文章get微信開源移動端數據庫組件WCDB的一切!》
《微信客戶端團隊負責人技術訪談:如何著手客戶端性能監控和優化》
《微信后臺基于時間序的海量數據冷熱分級架構設計實踐》
《微信團隊原創分享:Android版微信的臃腫之困與模塊化實踐之路》
《微信后臺團隊:微信后臺異步消息隊列的優化升級實踐分享》
《微信團隊原創分享:微信客戶端SQLite數據庫損壞修復實踐》
《騰訊原創分享(一):如何大幅提升移動網絡下手機QQ的圖片傳輸速度和成功率》
《騰訊原創分享(二):如何大幅壓縮移動網絡下APP的流量消耗(下篇)》
《騰訊原創分享(三):如何大幅壓縮移動網絡下APP的流量消耗(上篇)》
《微信Mars:微信內部正在使用的網絡層封裝庫,即將開源》
《如約而至:微信自用的移動端IM網絡層跨平臺組件庫Mars已正式開源》
(本文已同步發布于:http://www.52im.net/thread-2568-1-1.html)