閱讀241 返回首頁    go gooseeker集搜客


微信朋友圈技術之道:三個人的後台團隊與每日十億的發布量 ...

概述              截止到2015年7月,微信每月活躍用戶約5.49億,朋友圈每天的發表量(包括讚和評論)超過10億,瀏覽量超過100億。得益於4G網絡的發展,以上數據仍有很快的增長,而且相對於PC互聯網時代,移動互聯網時代的峰值要來得更加凶勐。比如,2015年元月的流量到了平時的2倍,而峰值則達到了平時峰值的2倍,相當於平時正常流量的5倍,這對整個係統的考驗是很殘酷的。本次分享將簡單介紹微信後台團隊的開發模式、微信朋友圈的架構以及在性能上的一些工作,供各位參考。
團隊與技術棧簡介              微信後台研發團隊由三位工程師組成。開發模式采用了敏捷的方式,大概一個月一個小版本,一個季度出一個大版本,另外每天都會有不停的後台更新,很多是用戶看不見的,也有一些是AB測試,比如選擇一億的用戶,或者一定百分比的用戶,或者一部分男性用戶和女性用戶來做AB測試。開發語言主要使用C++,正在往C++11上遷移,編譯器在往GCC 4.8.2遷移。       服務器的配置基本都是普通的服務器,最好的服務器也就是64G內存,這部分占比不多,大部分是32G內存,也有很少一部分8G內存的。硬盤是SSD和SATA都有。CPU以16核居多,有一部分新機器是32核。至於帶寬則是比較多的,對外帶寬很大。
微信朋友圈的架構概述              整個微信是微服務的架構,每一個請求後麵可能會涉及到幾百個服務,每一個服務都有一個QoS,目的是對一些重要的服務進行保證。比如除夕晚上流量達到平時的5倍,這時整個係統的性能肯定不夠,所以要優先保證什麼呢?優先保證支付,優先保證紅包的體驗。紅包體驗保證了,再保證消息,比如點對點兩人之間的消息。這兩個保證的前提下,再保證群聊。如果群聊也能保證,再保證朋友圈。性能不夠時將優先級低的服務暫時停掉,這個過程是不需要人工幹預的。               微信的架構跟普通的架構差不多,最上麵是終端通過接入服務器接進來。接入層主要是長連接,長連接主要是為了安卓係統,一個是減少建立新連接的性能消耗,另一個是為了推送通知,因為Google服務在國內基本是不可用的,安卓係統上的推送通知都是用長連接完成。              然後到邏輯層。邏輯層包括注冊、消息、群聊、朋友圈等等,還有iOS係統的通知。iOS係統跟安卓不一樣在於,一個iOS App進入後台之後隻有大概15秒的存活期,所以iOS上的推送通知要用API的Push完成,不在接入層做。             再往下走就是存儲代理層,這一層主要負責一些關鍵數據的維護操作,比如用戶在賬號裏麵的動作操作和事故信息。存儲代理層下麵對接KV存儲,這個KV存儲是不負責業務邏輯的,隻是單純的Key-Value映射,以及負載均衡和容錯。(有關KV存儲係統的詳細說明,可以參考微信架構師許家滔在QCon北京2014上的演講“微信後台存儲架構”。)
涉及朋友圈數據的有四個核心的表:
一個是發布。發布數據記錄了來自所有用戶所有的feed,比如一個用戶發布了幾張圖片,每張圖片的URL是什麼,在CDN裏的URL是什麼,它有哪些元屬性,誰可以看,誰不可以看等等。
一個是相冊。相冊是每個用戶獨立的,記錄了該用戶所發布的所有內容。
一個是評論。評論就是針對某個具體發布的朋友評論和點讚操作。
一個是時間線。所謂“刷朋友圈”,就是刷時間線,就是一個用戶所有朋友的發布內容。
上麵提到過,微信現在每天的發布有10億多,瀏覽量超過100億,對性能的要求很高,所以上麵的存儲都是做成可以水平擴展的。對於水平擴展的實現,下麵舉例說明。
微信朋友圈的工作流程概述              比如有兩個用戶小王和Mary。小王和Mary各自有各自的相冊,可能在同一台服務器上,也可能在不同的服務器上。現在小王上傳了一張圖片到自己的朋友圈。上傳圖片不經過微信後台服務器,而是直接上傳到最近的騰訊CDN節點,所以非常快。圖片上傳到該CDN後,小王的微信客戶端會通知微信的朋友圈CDN:這裏有一個新的發布(比如叫K2),這個發布的圖片URL是什麼,誰能看到這些圖片,等等此類的元數據,來把這個發布寫到發布的表裏。              在發布的表寫完之後,會把這個K2的發布索引到小王的相冊表裏。所以相冊表其實是很小的,裏麵隻有索引指針。相冊表寫好了之後,會觸發一個批處理的動作。這個動作就是去跟小王的每個好友說,小王有一個新的發布,請把這個發布插入到每個好友的時間線裏麵去。           然後比如說現在Mary上朋友圈了,而Mary是小王的一個好友。Mary拉自己的時間線的時候,時間線會告訴到有一個新的發布K2,然後Mary的微信客戶端就會去根據K2的元數據去獲取圖片在CDN上的URL,把圖片拉到本地。
       在這個過程中,發布是很重的,因為一方麵要寫一個自己的數據副本,然後還要把這個副本的指針插到所有好友的時間線裏麵去。如果一個用戶有幾百個好友的話,這個過程會比較慢一些。這是一個單數據副本寫擴散的過程。但是相對應的,讀取就很簡單了,每一個用戶隻需要讀取自己的時間線表,就這一個動作就行,而不需要去遍曆所有好友的相冊表。
       為什麼選擇這樣一個寫擴散的模型?因為讀是有很多失敗的。一個用戶如果要去讀兩百個好友的相冊表,極端情況下可能要去兩百個服務器上去問,這個失敗的可能性是很大的。但是寫失敗了就沒關係,因為寫是可以等待的,寫失敗了就重新去拷貝,直到插入成功為止。所以這樣一個模型可以很大的減少服務的開銷。至於讚和評論的實現,是相對簡單的。上麵說了微信後台有一個專門的表存儲評論和讚的數據,比如Kate是Mary和小王的朋友的話,刷到了K2這一條發布,就會同時從評論表裏麵拉取對應K2的、Mary留下的評論內容,插入到K2內容的下方。而如果另一個人不是Mary和小王的共同朋友,則不會看到這條評論。
微信朋友圈的容災
        容災有不同的層次,先看區域性的。微信在上海有一個IDC,該IDC是由三個獨立的園區——A、B、C三個園區構成的。每一個園區都有獨立的供電、製冷,獨立的帶寬,帶寬同時連接聯通、電信,而且每個園區的容量都有富餘。三個園區直接有高速連接。所以無論任何一個區,比如C區整個不可用了,那麼用戶的客戶端會自動連接到另外兩個區,這兩個區有足夠的容量承載所有的服務。這種切換是無損的、無感知的。
       第二個層次的容災是跨地域的。微信最早在國內有一個上海的數據中心,這個數據中心承載了全國所有的用戶。後來有一天上海來了個海嘯還是什麼的,所有數據都沒了,於是後來在深圳又建立一個數據中心,上海服務北方用戶,深圳服務南方。後來因為微信發展海外用戶,於是在香港建立了第三個數據中心,主要服務東南亞、南亞、中東和非洲。後來在加拿大又建立了第四個數據中心,主要服務美洲和歐洲。
      這第二個層次的數據中心跟上麵說的園區不太一樣。每一個微信用戶事實上都屬於一個特定的數據中心,比如兩個北方的用戶,他們的數據都在上海的數據中心,如果說上海數據中心跟其他數據中心的連接斷了,這兩個用戶之間的通信是不會受到影響的。但如果有一個外國朋友在加拿大的數據中心,那麼他跟國內用戶的通信就可能受到影響。數據中心之間是有專線連接的,但實際上國內到國外的專線渠道並不太有保障,所以專線出問題的時候,兩個數據中心之間的數據交換會切換到公網上,走普通的互聯網。
      新建一個數據中心涉及到很多同步,微信消息的數據同步是通過一個idcqueue組件實現的,是一個異步的數據同步方式。這個異步的寫操作可能會由於網絡阻塞或者其他原因,慢個一兩秒種、幾分鍾甚至半天,但它會一直重試,能夠保持正確性。而對於朋友圈來說,朋友圈是多數據副本的模型,那麼多數據副本在跨數據中心同步的時候如何保證正確性,如何保證沒有衝突?
     解法其實也簡單,隻要單項同步最初的發布寫操作。比如小王這個用戶是在上海數據中心的,他在自己相冊上新增了一條發布K2,那麼就隻要單項同步把K2寫到香港去就好了。反過來,比如Mary是在香港,那麼她有新的發布,隻要在香港寫進去之後,單項同步到上海就可以了。這樣就不存在時間線多數據副本同步的問題了,隻要在各個數據中心內分別做批處理。
     當然有關這一塊還有很多細節的問題,尤其是因為國內到國外的網絡延遲很大,從大陸ping美國可能兩百個毫秒,ping阿根廷或者南非可能有四百個毫秒,另外公網的丟包也比較嚴重,這對於數據同步的實現是很有影響的。這種情況就不適合用TCP了,TCP是針對大帶寬、小延遲、有序的環境設計的,所以微信在跨數據中心做數據同步這一塊就自己研發了一套類TCP的協議,這種協議對高延遲、高丟包有很高的容忍度,能夠做到每秒同步幾百兆到上G的數據。另一方麵,由於從專線切換到公網存在信息安全隱患,這其中的數據加密也是很重要的一個工作。
本文根據微信高級工程師、朋友圈負責人陳明在2015年ArchSummit深圳大會的演講“微信朋友圈技術之道”整理而成。

最後更新:2017-01-09 14:08:06

  上一篇:go 一行R代碼實現數據分析可視化
  下一篇:go 大數據的問題03:園中有金不在金——大數據的價值