微信多點登陸,消息漫遊,假如讓你來實現?

有朋友問:數據庫

  • 微信如何實現手機端、PC端同時登陸,同時收消息?
  • 微信能不能實現,換一個手機,仍能拉取到歷史消息?
    這是多點登陸和消息漫遊的問題。

什麼是多點登陸?

以微信爲例,能夠PC端,phone端同時登陸,同時收發消息。
畫外音:須要注意的是,一個端只能登陸一個實例,例如同一個QQ號,在pc1上登陸,再到pc2上登陸,後者會把前者踢出,pc1會收到通知「你已在別處登陸xxoo」。
微信

什麼是消息漫遊?

在任何一個終端的任何一個實例登陸,都可以拉取到全部歷史聊天消息,這個就是消息漫遊。
畫外音:微信目前只支持「多點登陸」同時收發在線消息,以及最近幾條消息的「消息漫遊」,沒有實現所有消息的「漫遊」。
架構

典型即時通信架構如何?

  • 典型即時通信架構能夠抽象成這麼幾層:
  • 客戶端:例如pc微信,手機qq
    服務端:
    入口層gate:保持與客戶端的鏈接;
    邏輯層logic、路由層router:實現業務邏輯,進行消息的路由;
    cache:用來存儲用戶的在線狀態,與接入節點(用戶具體鏈接在哪一個gate節點);
    db:固化存儲消息,羣信息,好友關係鏈等信息;
    畫外音:都須要考慮高可用,擴展性。
    微信多點登陸,消息漫遊,假如讓你來實現?
    一個典型的消息投遞流程如上圖步驟1-5:
    (1) 用戶A登陸在gate1上,發出消息;
    (2) gate1將消息給logic/router;
    (3) logic/router查詢接收方的在線狀態(B在線,C不在線);
    (4.1) 假設接收方C不在線,存儲離線;
    (4.2) 假設接收方B在線,且登陸在gate2上,消息投遞給gate2;
    (5) gate2將消息投遞給B;
    畫外音:單對單消息有一系列應用層超時、重傳、確認、去重的機制,以保證消息的可靠投遞,這不是本文的重點,不進行展開。














實現「接收方」多點登錄,架構要作什麼調整?
微信多點登陸,消息漫遊,假如讓你來實現?
接收方多點登陸,pc也登陸,phone也登陸,後一端登陸不會將前一端踢出,cache中存儲狀態與登陸點時,再也不以user_id爲key,改成以user_id+終端類型爲key便可。

ide

單點登陸

B:online(狀態),gate2(登陸點)優化

多點登錄

B+pc:online(狀態),gate2(登陸點)
B+phone:online(狀態),gate3(登陸點)
spa

當用戶A給用戶B發送消息時,取出全部B的登陸點,進行消息羣發便可(如上圖中步驟4與步驟5)。
畫外音:接收方多點登陸,比較容易。
架構設計

實現「發送方」多點登錄,架構要作什麼調整?

有朋友可能要問,發送方和多點登陸有什麼關係?
假設:
用戶A登陸了兩個點,A1和A2;
用戶B登陸了兩個點,B1和B2;
這樣:
A(A1發出的)發送消息給B(B1和B2);
B(B1發出的)發送消息給A(A1和A2);
不就能夠了麼?






設計

其實否則:
A(A1發出的)發送消息給B(B1和B2);
B(B1發出的)發送消息給A(A1和A2);
可是:
A2端雖然收到了全部B回覆的消息,但消息實際上是在A1端發出的,故A2端只知道聊天消息的一半(全部B的回覆),缺失了聊天的上下文(全部A1端的發出)。
畫外音:這個邏輯有點繞,多看幾遍。




router

故,若是發送方也進行了多點登陸,發送出去的任何消息,除了要投遞給多點登陸的接收方,還須要投遞給多點登陸的發送方。
畫外音:發送方發出的消息,也須要發給「發送方」。
微信多點登陸,消息漫遊,假如讓你來實現?
如上圖,發送方A和接收方B都進行了多點登錄,cache中存儲的信息爲:
A+pc:online(狀態),gate0(登陸點)
A+phone:online(狀態),gate1(登陸點)
B+pc:online(狀態),gate2(登陸點)
B+phone:online(狀態),gate3(登陸點)






blog

當用戶A(phone端)給用戶B發送消息時,除了要投遞給B的全部多點登陸端,還須要投遞給A多點登錄的其餘端(pc端),如上圖中步驟4與步驟5。

只有這樣,才能在全部用戶的全部端,恢復與還原雙方聊天的上下文。
畫外音:搞清楚了原理,修改並不難。

實現「消息漫遊」,架構要作什麼調整?

若是不須要支持「消息漫遊」,對於在線消息,若是用戶接收到,是不須要存儲到數據庫的。但若是要支持「換一臺機器也能看到歷史的聊天消息」,就須要對全部消息進行存儲。

微信多點登陸,消息漫遊,假如讓你來實現?
消息投遞如上圖,用戶A發送消息給用戶B,雖然B在線,仍然要增長一個步驟2.5,在投遞以前進行存儲,以備B的其餘端登錄時,能夠拉取到歷史消息。

微信多點登陸,消息漫遊,假如讓你來實現?
消息拉取如上圖,本來不在線的B(phone端)從新登陸了,怎麼拉取歷史消息呢?

只須要在客戶端本地存儲一個上一次拉取到的msg_id(time),到服務端從新拉取便可。

這裏還有個問題,因爲服務端存儲全部消息成本是很是高的,因此通常「消息漫遊」是有時間(或者消息數)限制,不能拉取全部全部幾年前的歷史消息,只能拉取最近的雲端消息。
畫外音:
你猜,微信有沒有存儲,幾年前的消息呢?
你猜,交一個超級會員費,是否是能夠查詢呢?


總結

「多點登陸」是指多個端同時登陸一個賬號,同時收發消息,關鍵點是:
(1) 須要在服務端存儲同一個用戶多個端的狀態與登錄點;
(2) 發出消息時,要對發送方的多端與接收端的多端,都進行消息投遞;

「消息漫遊」是指一個用戶在任何端,均可以拉取到歷史消息,關鍵點是:
(1) 全部消息存儲在雲端;
(2) 每一個端本地存儲last_msg_id,在登陸時能夠到雲端同步歷史消息;
(3) 雲端存儲全部消息成本較高,通常會對歷史消息時間(或者條數)進行限制;


假如你來實現,你會怎麼作?
但願你們有收穫。
微信多點登陸,消息漫遊,假如讓你來實現?

架構師之路-分享可落地的技術文章

相關推薦:《GFS架構啓示》《Google MapReduce解決什麼問題?》《Google MapReduce巧妙優化思路?》《Google MapReduce架構設計實踐》《MapReduce,顛覆了分層架構的本質?》

相關文章
相關標籤/搜索