本文來自網易云信團隊的技術分享,原創發表于網易云信公眾號,原文鏈接:mp.weixin.qq.com/s/LT2dASI7QVpcOVxDAsMeVg,收錄時有改動。
1、引言
在不了解IM技術的人眼里,群聊是再平常不過的功能而已,萬人群聊?應該也不難實現吧?!
確實,從前端功能界面上來看,群聊無非就是個循環向群員發送消息的一對多聊天消息分發模式而已,難在何處?
真實的情況是,群聊是IM系統中的高難度技術點之一。難在哪?難在服務端!從某種角度上說,群聊功能的架構設計和技術實現的品質,可以代表這款IM軟件的技術水平。
群聊從后臺的技術實現上說,至少有以下難點:
1)如何高效地進行大量群員消息的分發?
2)如何高效地管理群員的在線狀態?
3)如何高效地讀取群員的在線狀態?
4)集群系統中,如何高效地保證群員消息的準確送達?
5)群聊消息該擴散寫還是擴散讀?
6)如何保證大量群聊消息分發的情況下不影響單聊消息體驗?
7)如何應對大群突發事件下的性能負載?
.... ....
目前,市面上主流的IM產品中,微信群是500人上限,QQ群是3000人上限(3000人群是按年付費升級,很貴,不是為一般用戶準備的)。一方面,從產品的定義上群成員數量不應過多,另一方面,技術成本也是個不可回避的因素。萬人群這種超大規模群的技術難度,更是難已想象。
本文內容是網易云信團隊為了響應萬人群聊功能需求,在設計實現萬人群聊技術方案中總結的技術實踐,借此機會分享給各IM開發者同行。
(本文同步發布于:http://www.52im.net/thread-2707-1-1.html)
學習交流:
- 即時通訊/推送技術開發交流5群:215477170[推薦]
- 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM》
2、概述
隨著移動互聯網的發展,即時通訊服務被廣泛應用到各個行業,客戶業務快速發展,傳統百人或千人上限的群聊已經無法滿足很多業務發展需求,因此網易云信IM推出萬人群服務。
萬人群場景需要解決以下問題:
1)消息需要按1:9999的比例進行轉發投遞,按常規消息處理流程將產生大量的子任務,對系統吞吐量的要求極高;
2)在微服務系統架構下,如果不采用一些優化方案,服務以及存儲(DB、緩存等)之間的QPS和網絡流量將非常高;
3)以群為單位的緩存(如群成員列表)內存存儲開銷較大(假設一個成員200Byte,萬人群約2MB);
4)群成員登錄后需要同步群離線消息,智能手機上App前后臺切換產生的較多登錄同步消息協議,因此需要優化消息同步方案。
為了解決以上問題,萬人群技術方案采用了“聚合+分層/組+增量”的設計思路:
3、萬人群消息的處理流程
1)按群維護在線群成員信息,主要包含兩部分(可以理解為兩個緩存集合):
a. 群成員在線信息:即用戶在線狀態變化(上線、下線)時,更新相應群的在線狀態信息(即動態維護群有哪些成員在線);
b. 成員IM長連接信息:即用戶新登錄時,更新用戶的Link信息(即登錄所在Link的地址信息,消息轉發時根據Link地址路由消息)。
2)IM Server收到群消息后,按群ID將消息路由到“群消息服務”模塊;
3)群消息模塊檢查并預處理消息內容,然后通過“群成員在線狀態”服務獲取在線成員,完成消息轉發的基礎工作。為了減少群消息模塊和群在線成員服務之間的網絡流量,采用了“本地緩存+增量同步”的緩存策略,即本地緩存記錄最后更新版本號和時間戳,每次同步群在線成員前先檢查緩存版本號是否有變更,若有則按最后更新時間增量同步;
4)通過“群成員在線服務”獲取在線群成員的Link鏈接信息,按Link分組路由消息(分組路由的原因:同一Link上的全部群成員只需要路由一條消息即可)。同樣為了減少網絡開銷,成員Link信息也采用“本地緩存+增量同步”的方案;
5)群消息采用“漫游+歷史”的存儲方案,漫游的消息存儲在分布式緩存中,歷史消息異步寫入HBase。用戶登錄后可以通過漫游快速的獲取到最新消息,并可以通過拉取歷史查看更早的消息。
4、萬人群方案本地緩存增量同步策略
拋開群在線狀態管理邏輯,群成員在線狀態服務可以簡單理解為分布式集中緩存。
增量同步技術方案如下:
如上圖所示:
1)數據緩存是一個集合,其包含了多個緩存數據項,每一個數據項帶有最后更新時間信息;另外緩存還有一個嚴格遞增的版本號;
2)緩存數據變更(新增、修改、刪除)后,需要增加版本號;
3)本地線程通過緩存管理讀取數據時,管理服務先檢查本地版本號和分布式緩存中的版本號是否一致,若不一致則按本地最新時間戳增量同步新數據項,并更新本地的版本號和最后更新時間(為了避免分布式集中緩存中并發寫入導致的增量時間戳不可靠問題,增量更新時可以將本地記錄的最后更新時間戳向前推移,比如減少20ms);
4)為避免本地多線程并發讀取相同數據項導致并發更新本地緩存的問題,可以按緩存數據合并更新請求,即解決并發問題還可以減少網絡開銷;
5)緩存數據由大量數據項構成,為了避免單個緩存數據太大,可以將數據項中的屬性業務場景精簡(冷熱分離),低頻次讀寫的屬性額外緩存。
5、萬人群水平擴容方案
萬人群采用大量本地緩存的方案解決消息處理性能和網絡流量的問題,因此本地存儲空間成了方案的瓶頸點。因此我們設計了分組路由的技術方案。
消息按群ID和路由策略定向路由到指定分組(集群)上處理,分組由多個計算節點組成,因此方案上可以做到分組內和分組間的水平擴縮容。
6、作為“云”服務,網易云信是如何實現萬人群所需的計算資源的?
由于萬人群對計算和存儲資源消耗比較高,在實施和運維方案上也有一定的特殊性,為了保證業務的可靠性和穩定性,網易云信是將萬人大群的能力,僅提供給專屬的云客戶(普通公有云客戶是無法使用的)。
之所以能從軟硬件基礎設施上為萬人群提供保障,網易云信的IM專有云必須具備以下資源能力:
1)需要專屬的獨立計算資源:保持計算資源獨立,且資源冗余度比公有云高,且需要保證不會受到公有云上其他客戶業務的影響;
2)需要專屬的獨立運維服務:從而根據客戶業務場景制定最佳的業務監控、彈性擴容、故障遷移等運維方案。
總之,萬人群聊的實現,過硬的技術方案設計和技術實現只是一方面,基礎計算設施資源和運維能力也是不可或缺。
所以,從今以后,不要隨隨便便就喊萬人群聊,甚至十萬人群聊,這不是想實現就能實現的哦!
附錄:更多群聊相關技術文章
《快速裂變:見證微信強大后臺架構從0到1的演進歷程(一)》
《如何保證IM實時消息的“時序性”與“一致性”?》
《IM單聊和群聊中的在線狀態同步應該用“推”還是“拉”?》
《IM群聊消息如此復雜,如何保證不丟不重?》
《微信后臺團隊:微信后臺異步消息隊列的優化升級實踐分享》
《移動端IM中大規模群消息的推送如何保證效率、實時性?》
《現代IM系統中聊天消息的同步和存儲方案探討》
《關于IM即時通訊群聊消息的亂序問題討論》
《IM群聊消息的已讀回執功能該怎么實現?》
《IM群聊消息究竟是存1份(即擴散讀)還是存多份(即擴散寫)?》
《一套高可用、易伸縮、高并發的IM群聊、單聊架構方案設計實踐》
《[技術腦洞] 如果把14億中國人拉到一個微信群里技術上能實現嗎?》
《IM群聊機制,除了循環去發消息還有什么方式?如何優化?》
《網易云信技術分享:IM中的萬人群聊技術方案實踐總結》
>> 更多同類文章 ……
(本文同步發布于:http://www.52im.net/thread-2707-1-1.html)