從0到1:微信后臺(tái)系統(tǒng)的演進(jìn)之路
2個(gè)月的開(kāi)發(fā)時(shí)間,微信后臺(tái)系統(tǒng)經(jīng)歷了從0到1的過(guò)程。從小步慢跑到快速成長(zhǎng),經(jīng)歷了平臺(tái)化到走出國(guó)門,微信交出的這份優(yōu)異答卷,解題思路是怎樣的?
從無(wú)到有
2011.1.21 微信正式發(fā)布。這一天距離微信項(xiàng)目啟動(dòng)日約為2個(gè)月。就在這2個(gè)月里,微信從無(wú)到有,大家可能會(huì)好奇這期間微信后臺(tái)做的最重要的事情是什么?
我想應(yīng)該是以下三件事:
確定了微信的消息模型
微信起初定位是一個(gè)通訊工具,作為通訊工具最核心的功能是收發(fā)消息。微信團(tuán)隊(duì)源于廣硏團(tuán)隊(duì),消息模型跟郵箱的郵件模型也很有淵源,都是存儲(chǔ)轉(zhuǎn)發(fā)。
圖 1 微信消息模型
圖1展示了這一消息模型,消息被發(fā)出后,會(huì)先在后臺(tái)臨時(shí)存儲(chǔ);為使接收者能更快接收到消息,會(huì)推送消息通知給接收者;最后客戶端主動(dòng)到服務(wù)器收取消息。
制定了數(shù)據(jù)同步協(xié)議
由于用戶的帳戶、聯(lián)系人和消息等數(shù)據(jù)都在服務(wù)器存儲(chǔ),如何將數(shù)據(jù)同步到客戶端就成了很關(guān)鍵的問(wèn)題。為簡(jiǎn)化協(xié)議,我們決定通過(guò)一個(gè)統(tǒng)一的數(shù)據(jù)同步協(xié)議來(lái)同步用戶所有的基礎(chǔ)數(shù)據(jù)。
最初的方案是客戶端記錄一個(gè)本地?cái)?shù)據(jù)的快照(Snapshot),需要同步數(shù)據(jù)時(shí),將Snapshot帶到服務(wù)器,服務(wù)器通過(guò)計(jì)算Snapshot與服務(wù)器數(shù)據(jù)的差異,將差異數(shù)據(jù)發(fā)給客戶端,客戶端再保存差異數(shù)據(jù)完成同步。不過(guò)這個(gè)方案有兩個(gè)問(wèn)題:一是Snapshot會(huì)隨著客戶端數(shù)據(jù)的增多變得越來(lái)越大,同步時(shí)流量開(kāi)銷大;二是客戶端每次同步都要計(jì)算Snapshot,會(huì)帶來(lái)額外的性能開(kāi)銷和實(shí)現(xiàn)復(fù)雜度。
幾經(jīng)討論后,方案改為由服務(wù)計(jì)算Snapshot,在客戶端同步數(shù)據(jù)時(shí)跟隨數(shù)據(jù)一起下發(fā)給客戶端,客戶端無(wú)需理解Snapshot,只需存儲(chǔ)起來(lái),在下次數(shù)據(jù)同步數(shù)據(jù)時(shí)帶上即可。同時(shí),Snapshot被設(shè)計(jì)得非常精簡(jiǎn),是若干個(gè)Key-Value的組合,Key代表數(shù)據(jù)的類型,Value代表給到客戶端的數(shù)據(jù)的最新版本號(hào)。Key有三個(gè),分別代表:帳戶數(shù)據(jù)、聯(lián)系人和消息。這個(gè)同步協(xié)議的一個(gè)額外好處是客戶端同步完數(shù)據(jù)后,不需要額外的ACK協(xié)議來(lái)確認(rèn)數(shù)據(jù)收取成功,同樣可以保證不會(huì)丟數(shù)據(jù):只要客戶端拿最新的Snapshot到服務(wù)器做數(shù)據(jù)同步,服務(wù)器即可確認(rèn)上次數(shù)據(jù)已經(jīng)成功同步完成,可以執(zhí)行后續(xù)操作,例如清除暫存在服務(wù)的消息等等。
此后,精簡(jiǎn)方案、減少流量開(kāi)銷、盡量由服務(wù)器完成較復(fù)雜的業(yè)務(wù)邏輯、降低客戶端實(shí)現(xiàn)的復(fù)雜度就作為重要的指導(dǎo)原則,持續(xù)影響著后續(xù)的微信設(shè)計(jì)開(kāi)發(fā)。記得有個(gè)比較經(jīng)典的案例是:我們?cè)谖⑿?.2版實(shí)現(xiàn)了群聊功能,但為了保證新舊版客戶端間的群聊體驗(yàn),我們通過(guò)服務(wù)器適配,讓1.0版客戶端也能參與群聊。
定型了后臺(tái)架構(gòu)
圖 2 微信后臺(tái)系統(tǒng)架構(gòu)
微信后臺(tái)使用三層架構(gòu):接入層、邏輯層和存儲(chǔ)層。
- 接入層提供接入服務(wù),包括長(zhǎng)連接入服務(wù)和短連接入服務(wù)。長(zhǎng)連接入服務(wù)同時(shí)支持客戶端主動(dòng)發(fā)起請(qǐng)求和服務(wù)器主動(dòng)發(fā)起推送;短連接入服務(wù)則只支持客戶端主動(dòng)發(fā)起請(qǐng)求。
- 邏輯層包括業(yè)務(wù)邏輯服務(wù)和基礎(chǔ)邏輯服務(wù)。業(yè)務(wù)邏輯服務(wù)封裝了業(yè)務(wù)邏輯,是后臺(tái)提供給微信客戶端調(diào)用的API。基礎(chǔ)邏輯服務(wù)則抽象了更底層和通用的業(yè)務(wù)邏輯,提供給業(yè)務(wù)邏輯服務(wù)訪問(wèn)。
- 存儲(chǔ)層包括數(shù)據(jù)訪問(wèn)服務(wù)和數(shù)據(jù)存儲(chǔ)服務(wù)。數(shù)據(jù)存儲(chǔ)服務(wù)通過(guò)MySQL和SDB(廣硏早期后臺(tái)中廣泛使用的Key-Table數(shù)據(jù)存儲(chǔ)系統(tǒng))等底層存儲(chǔ)系統(tǒng)來(lái)持久化用戶數(shù)據(jù)。數(shù)據(jù)訪問(wèn)服務(wù)適配并路由數(shù)據(jù)訪問(wèn)請(qǐng)求到不同的底層數(shù)據(jù)存儲(chǔ)服務(wù),面向邏輯層提供結(jié)構(gòu)化的數(shù)據(jù)服務(wù)。比較特別的是,微信后臺(tái)每一種不同類型的數(shù)據(jù)都使用單獨(dú)的數(shù)據(jù)訪問(wèn)服務(wù)和數(shù)據(jù)存儲(chǔ)服務(wù),例如帳戶、消息和聯(lián)系人等等都是獨(dú)立的。
微信后臺(tái)主要使用C++。后臺(tái)服務(wù)使用Svrkit框架搭建,服務(wù)之間通過(guò)同步RPC進(jìn)行通訊。
圖 3 Svrkit 框架
Svrkit是另一個(gè)廣硏后臺(tái)就已經(jīng)存在的高性能RPC框架,當(dāng)時(shí)尚未廣泛使用,但在微信后臺(tái)卻大放異彩。作為微信后臺(tái)基礎(chǔ)設(shè)施中最重要的一部分,Svrkit這幾年一直不斷在進(jìn)化。我們使用Svrkit構(gòu)建了數(shù)以千計(jì)的服務(wù)模塊,提供數(shù)萬(wàn)個(gè)服務(wù)接口,每天RPC調(diào)用次數(shù)達(dá)幾十萬(wàn)億次。
這三件事影響深遠(yuǎn),乃至于5年后的今天,我們?nèi)岳^續(xù)沿用最初的架構(gòu)和協(xié)議,甚至還可以支持當(dāng)初1.0版的微信客戶端。
這里有一個(gè)經(jīng)驗(yàn)教訓(xùn)——運(yùn)營(yíng)支撐系統(tǒng)真的很重要。第一個(gè)版本的微信后臺(tái)是倉(cāng)促完成的,當(dāng)時(shí)只是完成了基礎(chǔ)業(yè)務(wù)功能,并沒(méi)有配套的業(yè)務(wù)數(shù)據(jù)統(tǒng)計(jì)等等。我們?cè)陂_(kāi)放注冊(cè)后,一時(shí)間竟沒(méi)有業(yè)務(wù)監(jiān)控頁(yè)面和數(shù)據(jù)曲線可以看,注冊(cè)用戶數(shù)是臨時(shí)從數(shù)據(jù)庫(kù)統(tǒng)計(jì)的,在線數(shù)是從日志里提取出來(lái)的,這些數(shù)據(jù)通過(guò)每個(gè)小時(shí)運(yùn)行一次的腳本(這個(gè)腳本也是當(dāng)天臨時(shí)加的)統(tǒng)計(jì)出來(lái),然后自動(dòng)發(fā)郵件到郵件組。還有其他各種業(yè)務(wù)數(shù)據(jù)也通過(guò)郵件進(jìn)行發(fā)布,可以說(shuō)郵件是微信初期最重要的數(shù)據(jù)門戶。
2011.1.21 當(dāng)天最高并發(fā)在線數(shù)是 491,而今天這個(gè)數(shù)字是4億。
小步慢跑
在微信發(fā)布后的4個(gè)多月里,我們經(jīng)歷了發(fā)布后火爆注冊(cè)的驚喜,也經(jīng)歷了隨后一直不溫不火的困惑。
這一時(shí)期,微信做了很多旨在增加用戶好友量,讓用戶聊得起來(lái)的功能。打通騰訊微博私信、群聊、工作郵箱、QQ/郵箱好友推薦等等。對(duì)于后臺(tái)而言,比較重要的變化就是這些功能催生了對(duì)異步隊(duì)列的需求。例如,微博私信需要跟外部門對(duì)接,不同系統(tǒng)間的處理耗時(shí)和速度不一樣,可以通過(guò)隊(duì)列進(jìn)行緩沖;群聊是耗時(shí)操作,消息發(fā)到群后,可以通過(guò)異步隊(duì)列來(lái)異步完成消息的擴(kuò)散寫(xiě)等等。
圖 4 單聊和群聊消息發(fā)送過(guò)程
圖4是異步隊(duì)列在群聊中的應(yīng)用。微信的群聊是寫(xiě)擴(kuò)散的,也就是說(shuō)發(fā)到群里的一條消息會(huì)給群里的每個(gè)人都存一份(消息索引)。為什么不是讀擴(kuò)散呢?有兩個(gè)原因:
- 群的人數(shù)不多,群人數(shù)上限是10(后來(lái)逐步加到20、40、100,目前是500),擴(kuò)散的成本不是太大,不像微博,有成千上萬(wàn)的粉絲,發(fā)一條微博后,每粉絲都存一份的話,一個(gè)是效率太低,另一個(gè)存儲(chǔ)量也會(huì)大很多;
- 消息擴(kuò)散寫(xiě)到每個(gè)人的消息存儲(chǔ)(消息收件箱)后,接收者到后臺(tái)同步數(shù)據(jù)時(shí),只需要檢查自己收件箱即可,同步邏輯跟單聊消息是一致的,這樣可以統(tǒng)一數(shù)據(jù)同步流程,實(shí)現(xiàn)起來(lái)也會(huì)很輕量。
異步隊(duì)列作為后臺(tái)數(shù)據(jù)交互的一種重要模式,成為了同步RPC服務(wù)調(diào)用之外的有力補(bǔ)充,在微信后臺(tái)被大量使用。
快速成長(zhǎng)
微信的飛速發(fā)展是從2.0版開(kāi)始的,這個(gè)版本發(fā)布了語(yǔ)音聊天功能。之后微信用戶量急速增長(zhǎng),2011.5用戶量破100萬(wàn)、2011.7 用戶量破1000萬(wàn)、2012.3 注冊(cè)用戶數(shù)突破1億。
伴隨著喜人成績(jī)而來(lái)的,還有一堆幸福的煩惱:
- 業(yè)務(wù)快速迭代的壓力
- 微信發(fā)布時(shí)功能很簡(jiǎn)單,主要功能就是發(fā)消息。不過(guò)在發(fā)語(yǔ)音之后的幾個(gè)版本里迅速推出了手機(jī)通訊錄、QQ離線消息、查看附近的人、搖一搖、漂流瓶和朋友圈等等功能。
- 有個(gè)廣為流傳的關(guān)于朋友圈開(kāi)發(fā)的傳奇——朋友圈歷經(jīng)4個(gè)月,前后做了30多個(gè)版本迭代才最終成型。其實(shí)還有一個(gè)鮮為人知的故事——那時(shí)候因?yàn)槿藛T比較短缺,朋友圈后臺(tái)長(zhǎng)時(shí)間只有1位開(kāi)發(fā)人員。
后臺(tái)穩(wěn)定性的要求:
用戶多了,功能也多了,后臺(tái)模塊數(shù)和機(jī)器量在不斷翻番,緊跟著的還有各種故障。
幫助我們順利度過(guò)這個(gè)階段的,是以下幾個(gè)舉措:
極簡(jiǎn)設(shè)計(jì)
雖然各種需求撲面而來(lái),但我們每個(gè)實(shí)現(xiàn)方案都是一絲不茍完成的。實(shí)現(xiàn)需求最大的困難不是設(shè)計(jì)出一個(gè)方案并實(shí)現(xiàn)出來(lái),而是需要在若干個(gè)可能的方案中,甄選出最簡(jiǎn)單實(shí)用的那個(gè)。
這中間往往需要經(jīng)過(guò)幾輪思考——討論——推翻的迭代過(guò)程,謀定而后動(dòng)有不少好處,一方面可以避免做出華而不實(shí)的過(guò)度設(shè)計(jì),提升效率;另一方面,通過(guò)詳盡的討論出來(lái)的看似簡(jiǎn)單的方案,細(xì)節(jié)考究,往往是可靠性最好的方案。
大系統(tǒng)小做
邏輯層的業(yè)務(wù)邏輯服務(wù)最早只有一個(gè)服務(wù)模塊(我們稱之為mmweb),囊括了所有提供給客戶端訪問(wèn)的API,甚至還有一個(gè)完整的微信官網(wǎng)。這個(gè)模塊架構(gòu)類似Apache,由一個(gè)CGI容器(CGIHost)和若干CGI組成(每個(gè)CGI即為一個(gè)API),不同之處在于每個(gè)CGI都是一個(gè)動(dòng)態(tài)庫(kù)so,由CGIHost動(dòng)態(tài)加載。
在mmweb的CGI數(shù)量相對(duì)較少的時(shí)候,這個(gè)模塊的架構(gòu)完全能滿足要求,但當(dāng)功能迭代加快,CGI量不斷增多之后,開(kāi)始出現(xiàn)問(wèn)題:
- 每個(gè)CGI都是動(dòng)態(tài)庫(kù),在某些CGI的共用邏輯的接口定義發(fā)生變化時(shí),不同時(shí)期更新上線的CGI可能使用了不同版本的邏輯接口定義,會(huì)導(dǎo)致在運(yùn)行時(shí)出現(xiàn)詭異結(jié)果或者進(jìn)程crash,而且非常難以定位;
- 所有CGI放在一起,每次大版本發(fā)布上線,從測(cè)試到灰度再到全面部署完畢,都是一個(gè)很漫長(zhǎng)的過(guò)程,幾乎所有后臺(tái)開(kāi)發(fā)人員都會(huì)被同時(shí)卡在這個(gè)環(huán)節(jié),非常影響效率;
- 新增的不太重要的CGI有時(shí)穩(wěn)定性不好,某些異常分支下會(huì)crash,導(dǎo)致CGIHost進(jìn)程無(wú)法服務(wù),發(fā)消息這些重要CGI受影響沒(méi)法運(yùn)行。
于是我們開(kāi)始嘗試使用一種新的CGI架構(gòu)——Logicsvr。
Logicsvr基于Svrkit框架。將Svrkit框架和CGI邏輯通過(guò)靜態(tài)編譯生成可直接使用HTTP訪問(wèn)的Logicsvr。我們將mmweb模塊拆分為8個(gè)不同服務(wù)模塊。拆分原則是:實(shí)現(xiàn)不同業(yè)務(wù)功能的CGI被拆到不同Logicsvr,同一功能但是重要程度不一樣的也進(jìn)行拆分。例如,作為核心功能的消息收發(fā)邏輯,就被拆為3個(gè)服務(wù)模塊:消息同步、發(fā)文本和語(yǔ)音消息、發(fā)圖片和視頻消息。
每個(gè)Logicsvr都是一個(gè)獨(dú)立的二進(jìn)制程序,可以分開(kāi)部署、獨(dú)立上線。時(shí)至今日,微信后臺(tái)有數(shù)十個(gè)Logicsvr,提供了數(shù)百個(gè)CGI服務(wù),部署在數(shù)千臺(tái)服務(wù)器上,每日客戶端訪問(wèn)量幾千億次。
除了API服務(wù)外,其他后臺(tái)服務(wù)模塊也遵循“大系統(tǒng)小做”這一實(shí)踐準(zhǔn)則,微信后臺(tái)服務(wù)模塊數(shù)從微信發(fā)布時(shí)的約10個(gè)模塊,迅速上漲到數(shù)百個(gè)模塊。
業(yè)務(wù)監(jiān)控
這一時(shí)期,后臺(tái)故障很多。比故障更麻煩的是,因?yàn)楸O(jiān)控的缺失,經(jīng)常有些故障我們沒(méi)法第一時(shí)間發(fā)現(xiàn),造成故障影響面被放大。
監(jiān)控的缺失一方面是因?yàn)樵诳焖俚^(guò)程中,重視功能開(kāi)發(fā),輕視了業(yè)務(wù)監(jiān)控的重要性,有故障一直是兵來(lái)將擋水來(lái)土掩;另一方面是基礎(chǔ)設(shè)施對(duì)業(yè)務(wù)邏輯監(jiān)控的支持度較弱。基礎(chǔ)設(shè)施提供了機(jī)器資源監(jiān)控和Svrkit服務(wù)運(yùn)行狀態(tài)的監(jiān)控。這個(gè)是每臺(tái)機(jī)器、每個(gè)服務(wù)標(biāo)配的,無(wú)需額外開(kāi)發(fā),但是業(yè)務(wù)邏輯的監(jiān)控就要麻煩得多了。當(dāng)時(shí)的業(yè)務(wù)邏輯監(jiān)控是通過(guò)業(yè)務(wù)邏輯統(tǒng)計(jì)功能來(lái)做的,實(shí)現(xiàn)一個(gè)監(jiān)控需要4步:
- 申請(qǐng)日志上報(bào)資源;
- 在業(yè)務(wù)邏輯中加入日志上報(bào)點(diǎn),日志會(huì)被每臺(tái)機(jī)器上的agent收集并上傳到統(tǒng)計(jì)中心;
- 開(kāi)發(fā)統(tǒng)計(jì)代碼;
- 實(shí)現(xiàn)統(tǒng)計(jì)監(jiān)控頁(yè)面。
可以想象,這種費(fèi)時(shí)費(fèi)力的模式會(huì)反過(guò)來(lái)降低開(kāi)發(fā)人員對(duì)加入業(yè)務(wù)監(jiān)控的積極性。于是有一天,我們?nèi)ス緝?nèi)的標(biāo)桿——即通后臺(tái)(QQ后臺(tái))取經(jīng)了,發(fā)現(xiàn)解決方案出乎意料地簡(jiǎn)單且強(qiáng)大:
1) 故障報(bào)告
之前每次故障后,是由QA牽頭出一份故障報(bào)告,著重點(diǎn)是對(duì)故障影響的評(píng)估和故障定級(jí)。新的做法是每個(gè)故障不分大小,開(kāi)發(fā)人員需要徹底復(fù)盤故障過(guò)程,然后商定解決方案,補(bǔ)充出一份詳細(xì)的技術(shù)報(bào)告。這份報(bào)告?zhèn)戎赜冢喝绾伪苊馔愋凸收显俅伟l(fā)生、提高故障主動(dòng)發(fā)現(xiàn)能力、縮短故障響應(yīng)和處理過(guò)程。
2) 基于 ID-Value 的業(yè)務(wù)無(wú)關(guān)的監(jiān)控告警體系
圖 5 基于 ID-Value 的監(jiān)控告警體系
監(jiān)控體系實(shí)現(xiàn)思路非常簡(jiǎn)單,提供了2個(gè)API,允許業(yè)務(wù)代碼在共享內(nèi)存中對(duì)某個(gè)監(jiān)控ID進(jìn)行設(shè)置Value或累加Value的功能。每臺(tái)機(jī)器上的Agent會(huì)定時(shí)將所有ID-Value上報(bào)到監(jiān)控中心,監(jiān)控中心對(duì)數(shù)據(jù)匯總?cè)霂?kù)后就可以通過(guò)統(tǒng)一的監(jiān)控頁(yè)面輸出監(jiān)控曲線,并通過(guò)預(yù)先配置的監(jiān)控規(guī)則產(chǎn)生報(bào)警。
對(duì)于業(yè)務(wù)代碼來(lái)說(shuō),只需在要被監(jiān)控的業(yè)務(wù)流程中調(diào)用一下監(jiān)控API,并配置好告警條件即可。這就極大地降低了開(kāi)發(fā)監(jiān)控報(bào)警的成本,我們補(bǔ)全了各種監(jiān)控項(xiàng),讓我們能主動(dòng)及時(shí)地發(fā)現(xiàn)問(wèn)題。新開(kāi)發(fā)的功能也會(huì)預(yù)先加入相關(guān)監(jiān)控項(xiàng),以便在少量灰度階段就能直接通過(guò)監(jiān)控曲線了解業(yè)務(wù)是否符合預(yù)期。
KVSvr
微信后臺(tái)每個(gè)存儲(chǔ)服務(wù)都有自己獨(dú)立的存儲(chǔ)模塊,是相互獨(dú)立的。每個(gè)存儲(chǔ)服務(wù)都有一個(gè)業(yè)務(wù)訪問(wèn)模塊和一個(gè)底層存儲(chǔ)模塊組成。業(yè)務(wù)訪問(wèn)層隔離業(yè)務(wù)邏輯層和底層存儲(chǔ),提供基于RPC的數(shù)據(jù)訪問(wèn)接口;底層存儲(chǔ)有兩類:SDB和MySQL。
SDB適用于以用戶UIN(uint32_t)為Key的數(shù)據(jù)存儲(chǔ),比方說(shuō)消息索引和聯(lián)系人。優(yōu)點(diǎn)是性能高,在可靠性上,提供基于異步流水同步的Master-Slave模式,Master故障時(shí),Slave可以提供讀數(shù)據(jù)服務(wù),無(wú)法寫(xiě)入新數(shù)據(jù)。
由于微信賬號(hào)為字母+數(shù)字組合,無(wú)法直接作為SDB的Key,所以微信帳號(hào)數(shù)據(jù)并非使用SDB,而是用MySQL存儲(chǔ)的。MySQL也使用基于異步流水復(fù)制的Master-Slave模式。
- 第1版的帳號(hào)存儲(chǔ)服務(wù)使用Master-Slave各1臺(tái)。Master提供讀寫(xiě)功能,Slave不提供服務(wù),僅用于備份。當(dāng)Master有故障時(shí),人工切讀服務(wù)到Slave,無(wú)法提供寫(xiě)服務(wù)。為提升訪問(wèn)效率,我們還在業(yè)務(wù)訪問(wèn)模塊中加入了memcached提供Cache服務(wù),減少對(duì)底層存儲(chǔ)訪問(wèn)。
- 第2版的帳號(hào)存儲(chǔ)服務(wù)還是Master-Slave各1臺(tái),區(qū)別是Slave可以提供讀服務(wù),但有可能讀到臟數(shù)據(jù),因此對(duì)一致性要求高的業(yè)務(wù)邏輯,例如注冊(cè)和登錄邏輯只允許訪問(wèn)Master。當(dāng)Master有故障時(shí),同樣只能提供讀服務(wù),無(wú)法提供寫(xiě)服務(wù)。
- 第3版的帳號(hào)存儲(chǔ)服務(wù)采用1個(gè)Master和多個(gè)Slave,解決了讀服務(wù)的水平擴(kuò)展能力。
- 第4版的帳號(hào)服務(wù)底層存儲(chǔ)采用多個(gè)Master-Slave組,每組由1個(gè)Master和多個(gè)Slave組成,解決了寫(xiě)服務(wù)能力不足時(shí)的水平擴(kuò)展能力。
- 最后還有個(gè)未解決的問(wèn)題:?jiǎn)蝹€(gè)Master-Slave分組中,Master還是單點(diǎn),無(wú)法提供實(shí)時(shí)的寫(xiě)容災(zāi),也就意味著無(wú)法消除單點(diǎn)故障。另外Master-Slave的流水同步延時(shí)對(duì)讀服務(wù)有很大影響,流水出現(xiàn)較大延時(shí)會(huì)導(dǎo)致業(yè)務(wù)故障。于是我們尋求一個(gè)可以提供高性能、具備讀寫(xiě)水平擴(kuò)展、沒(méi)有單點(diǎn)故障、可同時(shí)具備讀寫(xiě)容災(zāi)能力、能提供強(qiáng)一致性保證的底層存儲(chǔ)解決方案,最終KVSvr應(yīng)運(yùn)而生。
KVSvr使用基于Quorum的分布式數(shù)據(jù)強(qiáng)一致性算法,提供Key-Value/Key-Table模型的存儲(chǔ)服務(wù)。傳統(tǒng)Quorum算法的性能不高,KVSvr創(chuàng)造性地將數(shù)據(jù)的版本和數(shù)據(jù)本身做了區(qū)分,將Quorum算法應(yīng)用到數(shù)據(jù)的版本的協(xié)商,再通過(guò)基于流水同步的異步數(shù)據(jù)復(fù)制提供了數(shù)據(jù)強(qiáng)一致性保證和極高的數(shù)據(jù)寫(xiě)入性能,另外KVSvr天然具備數(shù)據(jù)的Cache能力,可以提供高效的讀取性能。
KVSvr一舉解決了我們當(dāng)時(shí)迫切需要的無(wú)單點(diǎn)故障的容災(zāi)能力。除了第5版的帳號(hào)服務(wù)外,很快所有SDB底層存儲(chǔ)模塊和大部分MySQL底層存儲(chǔ)模塊都切換到KVSvr。隨著業(yè)務(wù)的發(fā)展,KVSvr也不斷在進(jìn)化著,還配合業(yè)務(wù)需要衍生出了各種定制版本?,F(xiàn)在的KVSvr仍然作為核心存儲(chǔ),發(fā)揮著舉足輕重的作用。
平臺(tái)化
2011.8 深圳舉行大運(yùn)會(huì)。微信推出“微信深圳大運(yùn)志愿者服務(wù)中心”服務(wù)號(hào),微信用戶可以搜索“szdy”將這個(gè)服務(wù)號(hào)加為好友,獲取大會(huì)相關(guān)的資訊。當(dāng)時(shí)后臺(tái)對(duì)“szdy”做了特殊處理,用戶搜索時(shí),會(huì)隨機(jī)返回“szdy01”,“szdy02”…,“szdy10”這10個(gè)微信號(hào)中的1個(gè),每個(gè)微信號(hào)背后都有一個(gè)志愿者在服務(wù)。
2011.9 “微成都”落戶微信平臺(tái),微信用戶可以搜索“wechengdu”加好友,成都市民還可以在“附近的人”看到這個(gè)號(hào),我們?cè)诤笈_(tái)給這個(gè)帳號(hào)做了一些特殊邏輯,可以支持后臺(tái)自動(dòng)回復(fù)用戶發(fā)的消息。
這種需求越來(lái)越多,我們就開(kāi)始做一個(gè)媒體平臺(tái),這個(gè)平臺(tái)后來(lái)從微信后臺(tái)分出,演變成了微信公眾平臺(tái),獨(dú)立發(fā)展壯大,開(kāi)始了微信的平臺(tái)化之路。除微信公眾平臺(tái)外,微信后臺(tái)的外圍還陸續(xù)出現(xiàn)了微信支付平臺(tái)、硬件平臺(tái)等等一系列平臺(tái)。
圖 6 微信平臺(tái)
走出國(guó)門
微信走出國(guó)門的嘗試開(kāi)始于3.0版本。從這個(gè)版本開(kāi)始,微信逐步支持繁體、英文等多種語(yǔ)言文字。不過(guò),真正標(biāo)志性的事情是第一個(gè)海外數(shù)據(jù)中心的投入使用。
海外數(shù)據(jù)中心
海外數(shù)據(jù)中心的定位是一個(gè)自治的系統(tǒng),也就是說(shuō)具備完整的功能,能夠不依賴于國(guó)內(nèi)數(shù)據(jù)中心獨(dú)立運(yùn)作。
1) 多數(shù)據(jù)中心架構(gòu)
圖 7 多數(shù)據(jù)中心架構(gòu)
系統(tǒng)自治對(duì)于無(wú)狀態(tài)的接入層和邏輯層來(lái)說(shuō)很簡(jiǎn)單,所有服務(wù)模塊在海外數(shù)據(jù)中心部署一套就行了。
但是存儲(chǔ)層就有很大麻煩了——我們需要確保國(guó)內(nèi)數(shù)據(jù)中心和海外數(shù)據(jù)中心能獨(dú)立運(yùn)作,但不是兩套隔離的系統(tǒng)各自部署,各玩各的,而是一套業(yè)務(wù)功能可以完全互通的系統(tǒng)。因此我們的任務(wù)是需要保證兩個(gè)數(shù)據(jù)中心的數(shù)據(jù)一致性,另外Master-Master架構(gòu)是個(gè)必選項(xiàng),也即兩個(gè)數(shù)據(jù)中心都需要可寫(xiě)。
2) Master-Master 存儲(chǔ)架構(gòu)
Master-Master架構(gòu)下數(shù)據(jù)的一致性是個(gè)很大的問(wèn)題。兩個(gè)數(shù)據(jù)中心之間是個(gè)高延時(shí)的網(wǎng)絡(luò),意味著在數(shù)據(jù)中心之間直接使用Paxos算法、或直接部署基于Quorum的KVSvr等看似一勞永逸的方案不適用。
最終我們選擇了跟Yahoo!的PNUTS系統(tǒng)類似的解決方案,需要對(duì)用戶集合進(jìn)行切分,國(guó)內(nèi)用戶以國(guó)內(nèi)上海數(shù)據(jù)中心為Master,所有數(shù)據(jù)寫(xiě)操作必須回到國(guó)內(nèi)數(shù)據(jù)中心完成;海外用戶以海外數(shù)據(jù)中心為Master,寫(xiě)操作只能在海外數(shù)據(jù)中心進(jìn)行。從整體存儲(chǔ)上看,這是一個(gè)Master-Master的架構(gòu),但細(xì)到一個(gè)具體用戶的數(shù)據(jù),則是Master-Slave模式,每條數(shù)據(jù)只能在用戶歸屬的數(shù)據(jù)中心可寫(xiě),再異步復(fù)制到其他數(shù)據(jù)中心。
圖 8 多數(shù)據(jù)中心的數(shù)據(jù)Master-Master架構(gòu)
3) 數(shù)據(jù)中心間的數(shù)據(jù)一致性
這個(gè)Master-Master架構(gòu)可以在不同數(shù)據(jù)中心間實(shí)現(xiàn)數(shù)據(jù)最終一致性。如何保證業(yè)務(wù)邏輯在這種數(shù)據(jù)弱一致性保證下不會(huì)出現(xiàn)問(wèn)題?
這個(gè)問(wèn)題可以被分解為2個(gè)子問(wèn)題:
- 用戶訪問(wèn)自己的數(shù)據(jù):
用戶可以滿世界跑,那是否允許用戶就近接入數(shù)據(jù)中心就對(duì)業(yè)務(wù)處理流程有很大影響。如果允許就近接入,同時(shí)還要保證數(shù)據(jù)一致性不影響業(yè)務(wù),就意味著要么用戶數(shù)據(jù)的Master需要可以動(dòng)態(tài)的改變;要么需要對(duì)所有業(yè)務(wù)邏輯進(jìn)行仔細(xì)梳理,嚴(yán)格區(qū)分本數(shù)據(jù)中心和跨數(shù)據(jù)中心用戶的請(qǐng)求,將請(qǐng)求路由到正確的數(shù)據(jù)中心處理。
考慮到上述問(wèn)題會(huì)帶來(lái)很高昂的實(shí)現(xiàn)和維護(hù)的復(fù)雜度,我們限制了每個(gè)用戶只能接入其歸屬數(shù)據(jù)中心進(jìn)行操作。如果用戶發(fā)生漫游,其漫游到的數(shù)據(jù)中心會(huì)自動(dòng)引導(dǎo)用戶重新連回歸屬數(shù)據(jù)中心。
這樣用戶訪問(wèn)自己數(shù)據(jù)的一致性問(wèn)題就迎刃而解了,因?yàn)樗胁僮鞅幌拗圃跉w屬數(shù)據(jù)中心內(nèi),其數(shù)據(jù)是有強(qiáng)一致性保證的。此外,還有額外的好處:用戶自己的數(shù)據(jù)(如:消息和聯(lián)系人等)不需要在數(shù)據(jù)中心間同步,這就大大降低了對(duì)數(shù)據(jù)同步的帶寬需求。
- 用戶訪問(wèn)其他用戶的數(shù)據(jù):
由于不同數(shù)據(jù)中心之間業(yè)務(wù)需要互通,用戶會(huì)使用到其他數(shù)據(jù)中心用戶創(chuàng)建的數(shù)據(jù)。例如,參與其他數(shù)據(jù)中心用戶創(chuàng)建的群聊,查看其他數(shù)據(jù)中心用戶的朋友圈等。
仔細(xì)分析后可以發(fā)現(xiàn),大部分場(chǎng)景下對(duì)數(shù)據(jù)一致性要求其實(shí)并不高。用戶稍遲些才見(jiàn)到自己被加入某個(gè)其他數(shù)據(jù)中心用戶建的群、稍遲些才見(jiàn)到某個(gè)好友的朋友圈動(dòng)態(tài)更新其實(shí)并不會(huì)帶來(lái)什么問(wèn)題。在這些場(chǎng)景下,業(yè)務(wù)邏輯直接訪問(wèn)本數(shù)據(jù)中心的數(shù)據(jù)。
當(dāng)然,還是有些場(chǎng)景對(duì)數(shù)據(jù)一致性要求很高。比方說(shuō)給自己設(shè)置微信號(hào),而微信號(hào)是需要在整個(gè)微信帳號(hào)體系里保證唯一的。我們提供了全局唯一的微信號(hào)申請(qǐng)服務(wù)來(lái)解決這一問(wèn)題,所有數(shù)據(jù)中心通過(guò)這個(gè)服務(wù)申請(qǐng)微信號(hào)。這種需要特殊處置的場(chǎng)景極少,不會(huì)帶來(lái)太大問(wèn)題。
4) 可靠的數(shù)據(jù)同步
數(shù)據(jù)中心之間有大量的數(shù)據(jù)同步,數(shù)據(jù)是否能夠達(dá)到最終一致,取決于數(shù)據(jù)同步是否可靠。為保證數(shù)據(jù)同步的可靠性,提升同步的可用性,我們又開(kāi)發(fā)一個(gè)基于Quorum算法的隊(duì)列組件,這個(gè)組件的每一組由3機(jī)存儲(chǔ)服務(wù)組成。與一般隊(duì)列的不同之處在于,這個(gè)組件對(duì)隊(duì)列寫(xiě)入操作進(jìn)行了大幅簡(jiǎn)化,3機(jī)存儲(chǔ)服務(wù)不需要相互通訊,每個(gè)機(jī)器上的數(shù)據(jù)都是順序?qū)?,?zhí)行寫(xiě)操作時(shí)在3機(jī)能寫(xiě)入成功2份即為寫(xiě)入成功;若失敗,則換另外一組再試。因此這個(gè)隊(duì)列可以達(dá)到極高的可用性和寫(xiě)入性能。每個(gè)數(shù)據(jù)中心將需要同步的數(shù)據(jù)寫(xiě)入本數(shù)據(jù)中心的同步隊(duì)列后,由其他數(shù)據(jù)中心的數(shù)據(jù)重放服務(wù)將數(shù)據(jù)拉走并進(jìn)行重放,達(dá)到數(shù)據(jù)同步的目的。
網(wǎng)絡(luò)加速
海外數(shù)據(jù)中心建設(shè)周期長(zhǎng),投入大,微信只在香港和加拿大有兩個(gè)海外數(shù)據(jù)中心。但世界那么大,即便是這兩個(gè)數(shù)據(jù)中心,也還是沒(méi)法輻射全球,讓各個(gè)角落的用戶都能享受到暢快的服務(wù)體驗(yàn)。
通過(guò)在海外實(shí)際對(duì)比測(cè)試發(fā)現(xiàn),微信客戶端在發(fā)消息等一些主要使用場(chǎng)景與主要競(jìng)品有不小的差距。為此,我們跟公司的架構(gòu)平臺(tái)部、網(wǎng)絡(luò)平臺(tái)部和國(guó)際業(yè)務(wù)部等兄弟部門一起合作,圍繞海外數(shù)據(jù)中心,在世界各地精心選址建設(shè)了數(shù)十個(gè)POP點(diǎn)(包括信令加速點(diǎn)和圖片CDN網(wǎng)絡(luò))。另外,通過(guò)對(duì)移動(dòng)網(wǎng)絡(luò)的深入分析和研究,我們還對(duì)微信的通訊協(xié)議做了大幅優(yōu)化。微信最終在對(duì)比測(cè)試中趕上并超過(guò)了主要的競(jìng)品。
精耕細(xì)作
三園區(qū)容災(zāi)
2013.7.22 微信發(fā)生了有史以來(lái)最大規(guī)模的故障,消息收發(fā)和朋友圈等服務(wù)出現(xiàn)長(zhǎng)達(dá)5個(gè)小時(shí)的故障,故障期間消息量跌了一半。故障的起因是上海數(shù)據(jù)中心一個(gè)園區(qū)的主光纖被挖斷,近2千臺(tái)服務(wù)器不可用,引發(fā)整個(gè)上海數(shù)據(jù)中心(當(dāng)時(shí)國(guó)內(nèi)只有這一個(gè)數(shù)據(jù)中心)的服務(wù)癱瘓。
故障時(shí),我們?cè)鴩L試把接入到故障園區(qū)的用戶切走,但收效甚微。雖然數(shù)百個(gè)在線模塊都做了容災(zāi)和冗余設(shè)計(jì),單個(gè)服務(wù)模塊看起來(lái)沒(méi)有單點(diǎn)故障問(wèn)題;但整體上看,無(wú)數(shù)個(gè)服務(wù)實(shí)例散布在數(shù)據(jù)中心各個(gè)機(jī)房的8千多臺(tái)服務(wù)器內(nèi),各服務(wù)RPC調(diào)用復(fù)雜,呈網(wǎng)狀結(jié)構(gòu),再加上缺乏系統(tǒng)級(jí)的規(guī)劃和容災(zāi)驗(yàn)證,最終導(dǎo)致故障無(wú)法主動(dòng)恢復(fù)。在此之前,我們知道單個(gè)服務(wù)出現(xiàn)單機(jī)故障不影響系統(tǒng),但沒(méi)人知道2千臺(tái)服務(wù)器同時(shí)不可用時(shí),整個(gè)系統(tǒng)會(huì)出現(xiàn)什么不可控的狀況。
其實(shí)在這個(gè)故障發(fā)生之前3個(gè)月,我們已經(jīng)在著手解決這個(gè)問(wèn)題。當(dāng)時(shí)上海數(shù)據(jù)中心內(nèi)網(wǎng)交換機(jī)異常,導(dǎo)致微信出現(xiàn)一個(gè)出乎意料的故障,在13分鐘的時(shí)間里,微信消息收發(fā)幾乎完全不可用。在對(duì)故障進(jìn)行分析時(shí),我們發(fā)現(xiàn)一個(gè)消息系統(tǒng)里一個(gè)核心模塊三個(gè)互備的服務(wù)實(shí)例都部署在同一機(jī)房。該機(jī)房的交換機(jī)故障導(dǎo)致這個(gè)服務(wù)整體不可用,進(jìn)而消息跌零。這個(gè)服務(wù)模塊是最早期(那個(gè)時(shí)候微信后臺(tái)規(guī)模小,大部分后臺(tái)服務(wù)都部署在一個(gè)數(shù)據(jù)園區(qū)里)的核心模塊,服務(wù)基于3機(jī)冗余設(shè)計(jì),年復(fù)一年可靠地運(yùn)行著,以至于大家都完全忽視了這個(gè)問(wèn)題。
為解決類似問(wèn)題,三園區(qū)容災(zāi)應(yīng)運(yùn)而生,目標(biāo)是將上海數(shù)據(jù)中心的服務(wù)均勻部署到3個(gè)物理上隔離的數(shù)據(jù)園區(qū),在任意單一園區(qū)整體故障時(shí),微信仍能提供無(wú)損服務(wù)。
1) 同時(shí)服務(wù)
傳統(tǒng)的數(shù)據(jù)中心級(jí)災(zāi)備方案是“兩地三中心”,即同城有兩個(gè)互備的數(shù)據(jù)中心,異地再建設(shè)一個(gè)災(zāi)備中心,這三個(gè)數(shù)據(jù)中心平時(shí)很可能只有一個(gè)在提供在線服務(wù),故障時(shí)再將業(yè)務(wù)流量切換到其他數(shù)據(jù)中心。這里的主要問(wèn)題是災(zāi)備數(shù)據(jù)中心無(wú)實(shí)際業(yè)務(wù)流量,在主數(shù)據(jù)中心故障時(shí)未必能正常切換到災(zāi)備中心,并且在平時(shí)大量的備份資源不提供服務(wù),也會(huì)造成大量的資源浪費(fèi)。
三園區(qū)容災(zāi)的核心是三個(gè)數(shù)據(jù)園區(qū)同時(shí)提供服務(wù),因此即便某個(gè)園區(qū)整體故障,那另外兩個(gè)園區(qū)的業(yè)務(wù)流量也只會(huì)各增加50%。反過(guò)來(lái)說(shuō),只需讓每個(gè)園區(qū)的服務(wù)器資源跑在容量上限的2/3,保留1/3的容量即可提供無(wú)損的容災(zāi)能力,而傳統(tǒng)“兩地三中心”則有多得多的服務(wù)器資源被閑置。此外,在平時(shí)三個(gè)園區(qū)同時(shí)對(duì)外服務(wù),因此我們?cè)诠收蠒r(shí),需要解決的問(wèn)題是“怎樣把業(yè)務(wù)流量切到其他數(shù)據(jù)園區(qū)?”,而不是“能不能把業(yè)務(wù)流量切到其他數(shù)據(jù)園區(qū)?”,前者顯然是更容易解決的一個(gè)問(wèn)題。
2) 數(shù)據(jù)強(qiáng)一致
三園區(qū)容災(zāi)的關(guān)鍵是存儲(chǔ)模塊需要把數(shù)據(jù)均勻分布在3個(gè)數(shù)據(jù)園區(qū),同一份數(shù)據(jù)要在不同園區(qū)有2個(gè)以上的一致的副本,這樣才能保證任意單一園區(qū)出災(zāi)后,可以不中斷地提供無(wú)損服務(wù)。由于后臺(tái)大部分存儲(chǔ)模塊都使用KVSvr,這樣解決方案也相對(duì)簡(jiǎn)單高效——將KVSvr的每1組機(jī)器都均勻部署在3個(gè)園區(qū)里。
3) 故障時(shí)自動(dòng)切換
三園區(qū)容災(zāi)的另一個(gè)難點(diǎn)是對(duì)故障服務(wù)的自動(dòng)屏蔽和自動(dòng)切換。即要讓業(yè)務(wù)邏輯服務(wù)模塊能準(zhǔn)確識(shí)別出某些下游服務(wù)實(shí)例已經(jīng)無(wú)法訪問(wèn),然后迅速自動(dòng)切到其他服務(wù)實(shí)例,避免被拖死。我們希望每個(gè)業(yè)務(wù)邏輯服務(wù)可以在不借助外部輔助信息(如建設(shè)中心節(jié)點(diǎn),由中心節(jié)點(diǎn)下發(fā)各個(gè)業(yè)務(wù)邏輯服務(wù)的健康狀態(tài))的情況下,能自行決策迅速屏蔽掉有問(wèn)題的服務(wù)實(shí)例,自動(dòng)把業(yè)務(wù)流量分散切到其他服務(wù)實(shí)例上。另外,我們還建設(shè)了一套手工操作的全局屏蔽系統(tǒng),可以在大型網(wǎng)絡(luò)故障時(shí),由人工介入屏蔽掉某個(gè)園區(qū)所有的機(jī)器,迅速將業(yè)務(wù)流量分散到其他兩個(gè)數(shù)據(jù)園區(qū)。
4) 容災(zāi)效果檢驗(yàn)
三園區(qū)容災(zāi)是否能正常發(fā)揮作用還需要進(jìn)行實(shí)際的檢驗(yàn),我們?cè)谏虾?shù)據(jù)中心和海外的香港數(shù)據(jù)中心完成三園區(qū)建設(shè)后,進(jìn)行了數(shù)次實(shí)戰(zhàn)演習(xí),屏蔽單一園區(qū)上千臺(tái)服務(wù),檢驗(yàn)容災(zāi)效果是否符合預(yù)期。特別地,為了避免隨著時(shí)間的推移某個(gè)核心服務(wù)模塊因?yàn)槟炒胃戮筒辉僦С秩龍@區(qū)容災(zāi)了,我們還搭建了一套容災(zāi)撥測(cè)系統(tǒng),每天對(duì)所有服務(wù)模塊選取某個(gè)園區(qū)的服務(wù)主動(dòng)屏蔽掉,自動(dòng)檢查服務(wù)整體失敗量是否發(fā)生變化,實(shí)現(xiàn)對(duì)三園區(qū)容災(zāi)效果的持續(xù)檢驗(yàn)。
性能優(yōu)化
之前我們?cè)跇I(yè)務(wù)迅速發(fā)展之時(shí),優(yōu)先支撐業(yè)務(wù)功能快速迭代,性能問(wèn)題無(wú)暇兼顧,比較粗放的貫徹了“先扛住再優(yōu)化”的海量之道。2014年開(kāi)始大幅縮減運(yùn)營(yíng)成本,性能優(yōu)化就被提上了日程。
我們基本上對(duì)大部分服務(wù)模塊的設(shè)計(jì)和實(shí)現(xiàn)都進(jìn)行了重新review,并進(jìn)行了有針對(duì)性的優(yōu)化,這還是可以節(jié)約出不少機(jī)器資源的。但更有效的優(yōu)化措施是對(duì)基礎(chǔ)設(shè)施的優(yōu)化,具體的說(shuō)是對(duì)Svrkit框架的優(yōu)化。Svrkit框架被廣泛應(yīng)用到幾乎所有服務(wù)模塊,如果框架層面能把機(jī)器資源使用到極致,那肯定是事半功倍的。
結(jié)果還真的可以,我們?cè)诨A(chǔ)設(shè)施里加入了對(duì)協(xié)程的支持,重點(diǎn)是這個(gè)協(xié)程組件可以不破壞原來(lái)的業(yè)務(wù)邏輯代碼結(jié)構(gòu),讓我們?cè)写a中使用同步RPC調(diào)用的代碼不做任何修改,就可以直接通過(guò)協(xié)程異步化。Svrkit框架直接集成了這個(gè)協(xié)程組件,然后美好的事情發(fā)生了,原來(lái)單實(shí)例最多提供上百并發(fā)請(qǐng)求處理能力的服務(wù),在重編上線后,轉(zhuǎn)眼間就能提供上千并發(fā)請(qǐng)求處理能力。Svrkit框架的底層實(shí)現(xiàn)在這一時(shí)期也做了全新的實(shí)現(xiàn),服務(wù)的處理能力大幅提高。
防雪崩
我們一直以來(lái)都不太擔(dān)心某個(gè)服務(wù)實(shí)例出現(xiàn)故障,導(dǎo)致這個(gè)實(shí)例完全無(wú)法提供服務(wù)的問(wèn)題,這個(gè)在后臺(tái)服務(wù)的容災(zāi)體系里可以被處理得很好。最擔(dān)心的是雪崩:某個(gè)服務(wù)因?yàn)槟承┰虺霈F(xiàn)過(guò)載,導(dǎo)致請(qǐng)求處理時(shí)間被大大拉長(zhǎng)。于是服務(wù)吞吐量下降,大量請(qǐng)求積壓在服務(wù)的請(qǐng)求隊(duì)列太長(zhǎng)時(shí)間了,導(dǎo)致訪問(wèn)這個(gè)服務(wù)的上游服務(wù)出現(xiàn)超時(shí)。更倒霉的是上游服務(wù)還經(jīng)常會(huì)重試,然后這個(gè)過(guò)載的服務(wù)僅有的一點(diǎn)處理能力都在做無(wú)用功(即處理完畢返回結(jié)果時(shí),調(diào)用端都已超時(shí)放棄),終于這個(gè)過(guò)載的服務(wù)徹底雪崩了。最糟糕的情況是上游服務(wù)每個(gè)請(qǐng)求都耗時(shí)那么久,雪崩順著RPC調(diào)用鏈一級(jí)級(jí)往上傳播,最終單個(gè)服務(wù)模塊的過(guò)載會(huì)引發(fā)大批服務(wù)模塊的雪崩。
我們?cè)谝环站o褲腰帶節(jié)省機(jī)器資源、消滅低負(fù)載機(jī)器后,所有機(jī)器的負(fù)載都上來(lái)了,服務(wù)過(guò)載變得經(jīng)常發(fā)生了。解決這一問(wèn)題的有力武器是Svrkit框架里的具有QoS保障的FastReject機(jī)制,可以快速拒絕掉超過(guò)服務(wù)自身處理能力的請(qǐng)求,即使在過(guò)載時(shí),也能穩(wěn)定地提供有效輸出。
安全加固
近年,互聯(lián)網(wǎng)安全事件時(shí)有發(fā)生,各種拖庫(kù)層出不窮。為保護(hù)用戶的隱私數(shù)據(jù),我們建設(shè)了一套數(shù)據(jù)保護(hù)系統(tǒng)——全程票據(jù)系統(tǒng)。其核心方案是,用戶登錄后,后臺(tái)會(huì)下發(fā)一個(gè)票據(jù)給客戶端,客戶端每次請(qǐng)求帶上票據(jù),請(qǐng)求在后臺(tái)服務(wù)的整個(gè)處理鏈條中,所有對(duì)核心數(shù)據(jù)服務(wù)的訪問(wèn),都會(huì)被校驗(yàn)票據(jù)是否合法,非法請(qǐng)求會(huì)被拒絕,從而保障用戶隱私數(shù)據(jù)只能用戶通過(guò)自己的客戶端發(fā)起操作來(lái)訪問(wèn)。
新的挑戰(zhàn)
資源調(diào)度系統(tǒng)
微信后臺(tái)有成千的服務(wù)模塊,部署在全球數(shù)以萬(wàn)計(jì)的服務(wù)器上,一直依靠人工管理。此外,微信后臺(tái)主要是提供實(shí)時(shí)在線服務(wù),每天的服務(wù)器資源占用在業(yè)務(wù)高峰和低谷時(shí)相差很大,在業(yè)務(wù)低谷時(shí)計(jì)算資源被白白浪費(fèi);另一方面,很多離線的大數(shù)據(jù)計(jì)算卻受制于計(jì)算資源不足,難以高效完成。
我們正在實(shí)驗(yàn)和部署的資源調(diào)度系統(tǒng)(Yard)可以把機(jī)器資源的分配和服務(wù)的部署自動(dòng)化、把離線任務(wù)的調(diào)度自動(dòng)化,實(shí)現(xiàn)了資源的優(yōu)化配置,在業(yè)務(wù)對(duì)服務(wù)資源的需求有變化時(shí),能更及時(shí)、更彈性地自動(dòng)實(shí)現(xiàn)服務(wù)的重新配置與部署。
高可用存儲(chǔ)
基于Quorum算法的KVSvr已經(jīng)實(shí)現(xiàn)了強(qiáng)一致性、高可用且高性能的Key-Value/Key-Table存儲(chǔ)。最近,微信后臺(tái)又誕生了基于Paxos算法的另一套存儲(chǔ)系統(tǒng),首先落地的是PhxSQL,一個(gè)支持完整MySQL功能,又同時(shí)具備強(qiáng)一致性、高可用和高性能的SQL存儲(chǔ)。
作者:張文瑞,微信后臺(tái)團(tuán)隊(duì)出品。
來(lái)源:微信公眾號(hào):infoqchina
- 目前還沒(méi)評(píng)論,等你發(fā)揮!