微信朋友圈技術(shù)之道:三個(gè)人的后臺(tái)團(tuán)隊(duì)與每日十億的發(fā)布量
![](http://image.woshipm.com/wp-files/img/36.jpg)
概述
截止到2015年7月,微信每月活躍用戶約5.49億,朋友圈每天的發(fā)表量(包括贊和評(píng)論)超過(guò)10億,瀏覽量超過(guò)100億。得益于4G網(wǎng)絡(luò)的發(fā)展,以上數(shù)據(jù)仍有很快的增長(zhǎng),而且相對(duì)于PC互聯(lián)網(wǎng)時(shí)代,移動(dòng)互聯(lián)網(wǎng)時(shí)代的峰值要來(lái)得更加兇猛。比如,2015年元月的流量到了平時(shí)的2倍,而峰值則達(dá)到了平時(shí)峰值的2倍,相當(dāng)于平時(shí)正常流量的5倍,這對(duì)整個(gè)系統(tǒng)的考驗(yàn)是很殘酷的。本次分享將簡(jiǎn)單介紹微信后臺(tái)團(tuán)隊(duì)的開發(fā)模式、微信朋友圈的架構(gòu)以及在性能上的一些工作,供各位參考。
團(tuán)隊(duì)與技術(shù)棧簡(jiǎn)介
微信后臺(tái)研發(fā)團(tuán)隊(duì)由三位工程師組成。開發(fā)模式采用了敏捷的方式,大概一個(gè)月一個(gè)小版本,一個(gè)季度出一個(gè)大版本,另外每天都會(huì)有不停的后臺(tái)更新,很多是用戶看不見的,也有一些是AB測(cè)試,比如選擇一億的用戶,或者一定百分比的用戶,或者一部分男性用戶和女性用戶來(lái)做AB測(cè)試。開發(fā)語(yǔ)言主要使用C++,正在往C++11上遷移,編譯器在往GCC 4.8.2遷移。
服務(wù)器的配置基本都是普通的服務(wù)器,最好的服務(wù)器也就是64G內(nèi)存,這部分占比不多,大部分是32G內(nèi)存,也有很少一部分8G內(nèi)存的。硬盤是SSD和SATA都有。CPU以16核居多,有一部分新機(jī)器是32核。至于帶寬則是比較多的,對(duì)外帶寬很大。
微信朋友圈的架構(gòu)概述
整個(gè)微信是微服務(wù)的架構(gòu),每一個(gè)請(qǐng)求后面可能會(huì)涉及到幾百個(gè)服務(wù),每一個(gè)服務(wù)都有一個(gè)QoS,目的是對(duì)一些重要的服務(wù)進(jìn)行保證。比如除夕晚上流量達(dá)到平時(shí)的5倍,這時(shí)整個(gè)系統(tǒng)的性能肯定不夠,所以要優(yōu)先保證什么呢??jī)?yōu)先保證支付,優(yōu)先保證紅包的體驗(yàn)。紅包體驗(yàn)保證了,再保證消息,比如點(diǎn)對(duì)點(diǎn)兩人之間的消息。這兩個(gè)保證的前提下,再保證群聊。如果群聊也能保證,再保證朋友圈。性能不夠時(shí)將優(yōu)先級(jí)低的服務(wù)暫時(shí)停掉,這個(gè)過(guò)程是不需要人工干預(yù)的。
微信的架構(gòu)跟普通的架構(gòu)差不多,最上面是終端通過(guò)接入服務(wù)器接進(jìn)來(lái)。接入層主要是長(zhǎng)連接,長(zhǎng)連接主要是為了安卓系統(tǒng),一個(gè)是減少建立新連接的性能消耗,另一個(gè)是為了推送通知,因?yàn)镚oogle服務(wù)在國(guó)內(nèi)基本是不可用的,安卓系統(tǒng)上的推送通知都是用長(zhǎng)連接完成。
然后到邏輯層。邏輯層包括注冊(cè)、消息、群聊、朋友圈等等,還有iOS系統(tǒng)的通知。iOS系統(tǒng)跟安卓不一樣在于,一個(gè)iOS App進(jìn)入后臺(tái)之后只有大概15秒的存活期,所以iOS上的推送通知要用API的Push完成,不在接入層做。
再往下走就是存儲(chǔ)代理層,這一層主要負(fù)責(zé)一些關(guān)鍵數(shù)據(jù)的維護(hù)操作,比如用戶在賬號(hào)里面的動(dòng)作操作和事故信息。存儲(chǔ)代理層下面對(duì)接KV存儲(chǔ),這個(gè)KV存儲(chǔ)是不負(fù)責(zé)業(yè)務(wù)邏輯的,只是單純的Key-Value映射,以及負(fù)載均衡和容錯(cuò)。(有關(guān)KV存儲(chǔ)系統(tǒng)的詳細(xì)說(shuō)明,可以參考微信架構(gòu)師許家滔在QCon北京2014上的演講“微信后臺(tái)存儲(chǔ)架構(gòu)”。)
涉及朋友圈數(shù)據(jù)的有四個(gè)核心的表:
- 一個(gè)是發(fā)布。發(fā)布數(shù)據(jù)記錄了來(lái)自所有用戶所有的feed,比如一個(gè)用戶發(fā)布了幾張圖片,每張圖片的URL是什么,在CDN里的URL是什么,它有哪些元屬性,誰(shuí)可以看,誰(shuí)不可以看等等。
- 一個(gè)是相冊(cè)。相冊(cè)是每個(gè)用戶獨(dú)立的,記錄了該用戶所發(fā)布的所有內(nèi)容。
- 一個(gè)是評(píng)論。評(píng)論就是針對(duì)某個(gè)具體發(fā)布的朋友評(píng)論和點(diǎn)贊操作。
- 一個(gè)是時(shí)間線。所謂“刷朋友圈”,就是刷時(shí)間線,就是一個(gè)用戶所有朋友的發(fā)布內(nèi)容。
上面提到過(guò),微信現(xiàn)在每天的發(fā)布有10億多,瀏覽量超過(guò)100億,對(duì)性能的要求很高,所以上面的存儲(chǔ)都是做成可以水平擴(kuò)展的。對(duì)于水平擴(kuò)展的實(shí)現(xiàn),下面舉例說(shuō)明。
微信朋友圈的工作流程概述
比如有兩個(gè)用戶小王和Mary。小王和Mary各自有各自的相冊(cè),可能在同一臺(tái)服務(wù)器上,也可能在不同的服務(wù)器上?,F(xiàn)在小王上傳了一張圖片到自己的朋友圈。上傳圖片不經(jīng)過(guò)微信后臺(tái)服務(wù)器,而是直接上傳到最近的騰訊CDN節(jié)點(diǎn),所以非常快。圖片上傳到該CDN后,小王的微信客戶端會(huì)通知微信的朋友圈CDN:這里有一個(gè)新的發(fā)布(比如叫K2),這個(gè)發(fā)布的圖片URL是什么,誰(shuí)能看到這些圖片,等等此類的元數(shù)據(jù),來(lái)把這個(gè)發(fā)布寫到發(fā)布的表里。
在發(fā)布的表寫完之后,會(huì)把這個(gè)K2的發(fā)布索引到小王的相冊(cè)表里。所以相冊(cè)表其實(shí)是很小的,里面只有索引指針。相冊(cè)表寫好了之后,會(huì)觸發(fā)一個(gè)批處理的動(dòng)作。這個(gè)動(dòng)作就是去跟小王的每個(gè)好友說(shuō),小王有一個(gè)新的發(fā)布,請(qǐng)把這個(gè)發(fā)布插入到每個(gè)好友的時(shí)間線里面去。
然后比如說(shuō)現(xiàn)在Mary上朋友圈了,而Mary是小王的一個(gè)好友。Mary拉自己的時(shí)間線的時(shí)候,時(shí)間線會(huì)告訴到有一個(gè)新的發(fā)布K2,然后Mary的微信客戶端就會(huì)去根據(jù)K2的元數(shù)據(jù)去獲取圖片在CDN上的URL,把圖片拉到本地。
在這個(gè)過(guò)程中,發(fā)布是很重的,因?yàn)橐环矫嬉獙懸粋€(gè)自己的數(shù)據(jù)副本,然后還要把這個(gè)副本的指針插到所有好友的時(shí)間線里面去。如果一個(gè)用戶有幾百個(gè)好友的話,這個(gè)過(guò)程會(huì)比較慢一些。這是一個(gè)單數(shù)據(jù)副本寫擴(kuò)散的過(guò)程。但是相對(duì)應(yīng)的,讀取就很簡(jiǎn)單了,每一個(gè)用戶只需要讀取自己的時(shí)間線表,就這一個(gè)動(dòng)作就行,而不需要去遍歷所有好友的相冊(cè)表。
為什么選擇這樣一個(gè)寫擴(kuò)散的模型?因?yàn)樽x是有很多失敗的。一個(gè)用戶如果要去讀兩百個(gè)好友的相冊(cè)表,極端情況下可能要去兩百個(gè)服務(wù)器上去問(wèn),這個(gè)失敗的可能性是很大的。但是寫失敗了就沒(méi)關(guān)系,因?yàn)閷懯强梢缘却模瑢懯×司椭匦氯タ截?,直到插入成功為止。所以這樣一個(gè)模型可以很大的減少服務(wù)的開銷。
至于贊和評(píng)論的實(shí)現(xiàn),是相對(duì)簡(jiǎn)單的。上面說(shuō)了微信后臺(tái)有一個(gè)專門的表存儲(chǔ)評(píng)論和贊的數(shù)據(jù),比如Kate是Mary和小王的朋友的話,刷到了K2這一條發(fā)布,就會(huì)同時(shí)從評(píng)論表里面拉取對(duì)應(yīng)K2的、Mary留下的評(píng)論內(nèi)容,插入到K2內(nèi)容的下方。而如果另一個(gè)人不是Mary和小王的共同朋友,則不會(huì)看到這條評(píng)論。
微信朋友圈的容災(zāi)
容災(zāi)有不同的層次,先看區(qū)域性的。微信在上海有一個(gè)IDC,該IDC是由三個(gè)獨(dú)立的園區(qū)——A、B、C三個(gè)園區(qū)構(gòu)成的。每一個(gè)園區(qū)都有獨(dú)立的供電、制冷,獨(dú)立的帶寬,帶寬同時(shí)連接聯(lián)通、電信,而且每個(gè)園區(qū)的容量都有富余。三個(gè)園區(qū)直接有高速連接。所以無(wú)論任何一個(gè)區(qū),比如C區(qū)整個(gè)不可用了,那么用戶的客戶端會(huì)自動(dòng)連接到另外兩個(gè)區(qū),這兩個(gè)區(qū)有足夠的容量承載所有的服務(wù)。這種切換是無(wú)損的、無(wú)感知的。
第二個(gè)層次的容災(zāi)是跨地域的。微信最早在國(guó)內(nèi)有一個(gè)上海的數(shù)據(jù)中心,這個(gè)數(shù)據(jù)中心承載了全國(guó)所有的用戶。后來(lái)有一天上海來(lái)了個(gè)海嘯還是什么的,所有數(shù)據(jù)都沒(méi)了,于是后來(lái)在深圳又建立一個(gè)數(shù)據(jù)中心,上海服務(wù)北方用戶,深圳服務(wù)南方。后來(lái)因?yàn)槲⑿虐l(fā)展海外用戶,于是在香港建立了第三個(gè)數(shù)據(jù)中心,主要服務(wù)東南亞、南亞、中東和非洲。后來(lái)在加拿大又建立了第四個(gè)數(shù)據(jù)中心,主要服務(wù)美洲和歐洲。
這第二個(gè)層次的數(shù)據(jù)中心跟上面說(shuō)的園區(qū)不太一樣。每一個(gè)微信用戶事實(shí)上都屬于一個(gè)特定的數(shù)據(jù)中心,比如兩個(gè)北方的用戶,他們的數(shù)據(jù)都在上海的數(shù)據(jù)中心,如果說(shuō)上海數(shù)據(jù)中心跟其他數(shù)據(jù)中心的連接斷了,這兩個(gè)用戶之間的通信是不會(huì)受到影響的。但如果有一個(gè)外國(guó)朋友在加拿大的數(shù)據(jù)中心,那么他跟國(guó)內(nèi)用戶的通信就可能受到影響。數(shù)據(jù)中心之間是有專線連接的,但實(shí)際上國(guó)內(nèi)到國(guó)外的專線渠道并不太有保障,所以專線出問(wèn)題的時(shí)候,兩個(gè)數(shù)據(jù)中心之間的數(shù)據(jù)交換會(huì)切換到公網(wǎng)上,走普通的互聯(lián)網(wǎng)。
新建一個(gè)數(shù)據(jù)中心涉及到很多同步,微信消息的數(shù)據(jù)同步是通過(guò)一個(gè)idcqueue組件實(shí)現(xiàn)的,是一個(gè)異步的數(shù)據(jù)同步方式。這個(gè)異步的寫操作可能會(huì)由于網(wǎng)絡(luò)阻塞或者其他原因,慢個(gè)一兩秒種、幾分鐘甚至半天,但它會(huì)一直重試,能夠保持正確性。而對(duì)于朋友圈來(lái)說(shuō),朋友圈是多數(shù)據(jù)副本的模型,那么多數(shù)據(jù)副本在跨數(shù)據(jù)中心同步的時(shí)候如何保證正確性,如何保證沒(méi)有沖突?
解法其實(shí)也簡(jiǎn)單,只要單項(xiàng)同步最初的發(fā)布寫操作。比如小王這個(gè)用戶是在上海數(shù)據(jù)中心的,他在自己相冊(cè)上新增了一條發(fā)布K2,那么就只要單項(xiàng)同步把K2寫到香港去就好了。反過(guò)來(lái),比如Mary是在香港,那么她有新的發(fā)布,只要在香港寫進(jìn)去之后,單項(xiàng)同步到上海就可以了。這樣就不存在時(shí)間線多數(shù)據(jù)副本同步的問(wèn)題了,只要在各個(gè)數(shù)據(jù)中心內(nèi)分別做批處理。
當(dāng)然有關(guān)這一塊還有很多細(xì)節(jié)的問(wèn)題,尤其是因?yàn)閲?guó)內(nèi)到國(guó)外的網(wǎng)絡(luò)延遲很大,從大陸ping美國(guó)可能兩百個(gè)毫秒,ping阿根廷或者南非可能有四百個(gè)毫秒,另外公網(wǎng)的丟包也比較嚴(yán)重,這對(duì)于數(shù)據(jù)同步的實(shí)現(xiàn)是很有影響的。這種情況就不適合用TCP了,TCP是針對(duì)大帶寬、小延遲、有序的環(huán)境設(shè)計(jì)的,所以微信在跨數(shù)據(jù)中心做數(shù)據(jù)同步這一塊就自己研發(fā)了一套類TCP的協(xié)議,這種協(xié)議對(duì)高延遲、高丟包有很高的容忍度,能夠做到每秒同步幾百兆到上G的數(shù)據(jù)。另一方面,由于從專線切換到公網(wǎng)存在信息安全隱患,這其中的數(shù)據(jù)加密也是很重要的一個(gè)工作。
作者簡(jiǎn)介
陳明,微信高級(jí)工程師、朋友圈負(fù)責(zé)人,2012年加入微信后臺(tái)團(tuán)隊(duì),負(fù)責(zé)微信后臺(tái)核心服務(wù)的研發(fā),包括朋友圈、即時(shí)通信、基礎(chǔ)設(shè)施等。他獲得清華大學(xué)計(jì)算機(jī)系學(xué)士和博士學(xué)位,研究方向是分布式系統(tǒng)。在加入微信前,他在騰訊搜索和微軟亞洲研究院工作多年,內(nèi)容包括搜索架構(gòu)與分布式存儲(chǔ)等。
文章來(lái)源@InfoQ技術(shù)沙龍
版權(quán)聲明:若該文章涉及版權(quán)問(wèn)題,請(qǐng)聯(lián)系我們主編,QQ:419297645
- 目前還沒(méi)評(píng)論,等你發(fā)揮!