<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Jack Jiang

    我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
    posts - 494, comments - 13, trackbacks - 0, articles - 1

    本文由融云技術團隊原創分享,原題“IM 消息數據存儲結構設計”,內容有修訂。

    1、引言

    在如今的移動互聯網時代,IM類產品已是我們生活中不可或缺的組成部分。像微信、釘釘、QQ等是典型的以 IM 為核心功能的社交產品。另外也有一些應用雖然IM功能不是核心,但IM能力也是其整個應用極其重要的組成部分,比如在線游戲、電商直播等應用。

    在IM技術應用場景越來越廣泛的前提下,對即時通訊IM技術的學習和掌握就顯的越來越有必要。

    在IM龐大的技術體系中,消息系統無疑是最核心的,而消息系統中,最關鍵的部分是消息的分發和存儲,而離線消息和歷史消息又是這個關鍵環節中不可回避的技術要點。

    本文將基于IM消息系統的技術實踐,分享關于離線消息和歷史消息的正確理解,以及具體的技術配合和實踐,希望能為你的離線消息和歷史消息技術設計帶來最佳實踐靈感。

    學習交流:

    - 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM

    - 開源IM框架源碼:https://github.com/JackJiang2011/MobileIMSDK 

    本文同步發布于:http://www.52im.net/thread-3887-1-1.html

    2、相關文章

    技術相關文章:

    1. 什么是IM系統的可靠性?
    2. 閑魚IM的在線、離線聊天數據同步機制優化實踐
    3. 閑魚億級IM消息系統的可靠投遞優化實踐
    4. 一套億級用戶的IM架構技術干貨(下篇):可靠性、有序性、弱網優化等
    5. IM消息送達保證機制實現(二):保證離線消息的可靠投遞
    6. 我是如何解決大量離線消息導致客戶端卡頓的

    融云技術團隊分享的其它文章:

    1. 融云安卓端IM產品的網絡鏈路保活技術實踐
    2. 全面揭秘億級IM消息的可靠投遞機制
    3. 解密融云IM產品的聊天消息ID生成策略
    4. 萬人群聊消息投遞方案的思考和實踐
    5. 基于WebRTC的實時音視頻首幀顯示時間優化實踐
    6. 融云IM技術分享:萬人群聊消息投遞方案的思考和實踐

    3、IM消息投遞的一般做法

    在通常的IM消息系統中,對于實時消息、離線消息、歷史消息大概都是下面這樣的技術思路。

    對于在線用戶:消息會直接實時發送到在線的接收方,消息發送完成后,服務器端并不會對消息進行落地存儲。

    而對于離線的用戶:服務器端會將消息存入到離線庫,當用戶登錄后,從離線庫中將離線消息拉走,然后服務器端將離線消息刪除。

    這樣實現的缺點就是消息不持久化,導致消息無法支持消息漫游,降低了消息的可靠性。

    PS:實際上,這其實也不能算是缺點,因為一些場景下存儲歷史消息并不是必須的,所謂的消息漫游能力也不是必備的,比如微信。

    而在我們設計的消息系統中,服務器只要接收到了發送方發上來的消息,在轉發給接收方的同時也會在離線數據庫及歷史消息庫中進行消息的落地存儲,而歷史消息的落地也就能支持消息漫游等相關功能了。

    4、什么是離線消息和歷史消息?

    關于離線消息和歷史消息,在技術上,我們是這樣定義。

    1)離線消息:

    離線消息就是用戶(即接收方)在離線過程中收到的消息,這些消息大多是用戶比較關心的消息,具有一定的時效性。

    以我們的系統經驗來說,我們的離線消息默認只保存最近七天的消息。

    用戶(即接收方)在下次登錄后會全量獲取這些離線消息,然后在客戶端根據聊天會話進行離線消息的UI展示(比如顯示一個未讀消息氣泡等)。

    PS:用戶離線的可能性在技術上其實是由很多種情況組成的,比如對方不在線、對方網絡斷掉了、對方手機崩潰了、服務器發送時出錯了等等,嚴格來講——只要無法實時發送成的消息,都算“離線消息”。

    2)歷史消息:

    歷史消息存儲了用戶所有的聊天消息,這些消息包括發出的消息以及接收到的消息。

    在客戶端獲取歷史消息時,通常是按照會話進行分頁獲取的。

    以我們的系統經驗來說,歷史消息的存儲時間我們設計默認為半年,當然這個時間可以按實際的產品運營規則來定,沒有硬性規定。

    5、IM消息的發送及存儲流程

    以下是我們系統整體的消息發送及存儲流程:

     如上圖所示:當用戶發送聊天消息到服務器端后,首先會進入到消息系統中,消息系統會對消息進行分發以及存儲。

    這個過程中:對于在線的接收方,會選擇直接推送消息。但是遇到接收方不在線或者是消息推送失敗的情況下,也會有另外的消息獲取方式,比如接收方會主動向服務器拉取未收到的消息。但是接收方何時來服務器拉取消息以及從哪里拉取是未知的,所以消息存入到離線庫的意義也就在這里。

    消息系統存儲離線的過程中,為了不影響整個系統的更為平穩,我們使用了MQ消息隊列進行IO解偶,所以聊天消息實際上是異步存入到離線庫中的(通過MQ進行慢IO解偶,這其實也是慣常做法)。

    在分發完消息后:消息服務會同步一份消息數據到歷史消息服務中,歷史消息服務同樣會對消息進行落地存儲。

    對于新的客戶端設備:會有同步消息的需求(所謂的消息漫游能力),而這也正是歷史消息的主要作用。在歷史消息庫中,客戶端是可以拉取任意會話的全量歷史消息的。

    6、IM離線消息、歷史消息在存儲邏輯上的區別

    6.1 概述

    通過上面的圖中能清晰的看到:

    • 1)離線消息我們存儲介質選用的是 Redis
    • 2)歷史消息我們選用的是 HBase

    對于為什么選用不同的存儲介質,其實我們考慮的是離線消息和歷史消息不同的業務場景和讀寫模式。

    下面我們重點介紹一下離線消息和歷史消息存儲的區別。

    6.2 離線消息存儲模式——“擴散寫”

    離線消息的存儲模式我們用的是擴散寫。

    如上圖所示:每個用戶都有自己單獨的收件箱和發件箱:

    • 1)收件箱存放的是需要向這個接收端同步的所有消息;
    • 2)發件箱里存放的是發送端發出的所有消息。

    以單聊為例:聊天中的兩人會話中,消息會產生兩次寫,即發送者的發件箱和接收端的收件箱。

    而在群的場景下:寫入會被更加的放大(擴散),如果群里有 N 個人,那一條群消息就會被擴散寫 N 次。

    小結一下:

    • 1)擴散寫的優點是:接收端的邏輯會非常清晰簡單,只需要從收件箱里讀取一次即可,大大降低了同步消息所需的讀的壓力;
    • 2)擴散寫的缺點是:寫入會被成指數地放大,特別是針對群這種場景。

    6.3 歷史消息存儲模式——“擴散讀”

    歷史消息的存儲模式我們用的是擴散讀。

    因為歷史消息中,每個會話都保存了整個會話的全量消息。在擴散讀這種模式下,每個會話的消息只保存一次。

    對比擴散寫模式,擴散讀的優點和缺點如下:

    • 1)優點是:寫入次數大大降低,特別是針對群消息,只需要存一次即可;
    • 2)缺點是:接收端接收消息非常的復雜和低效,因為這種模式客戶端想拉取到所有消息就只能每個會話同步一次,讀就會被放大,而且可能會產生很多次無效的讀,因為有些會話可能根本沒有新消息。

    6.4 小結

    在 IM 這種應用場景下,通常會用到擴散寫這種消息同步模型,一條消息產生一條,但是可能會被讀多次,是典型的讀多寫少的場景。

    一個優化好的IM系統,必須從設計上平衡讀寫壓力,避免讀或者寫任意一個維度達到天花板。

    當然擴散寫這種模式也有其弊端,比如萬人群,會導致一條消息,寫入了一萬次。

    綜合來講:我們需要根據自己的業務場景做相應設計選擇,以我們的IM系統為例,就是是根據了離線和歷史消息的不同場景選擇了寫擴散和讀擴散的組合模式。適合的才是最好的,沒有必要死搬硬套理論。

    7、IM客戶端的拉取消息邏輯

    7.1 離線消息拉取邏輯

    對于IM客戶端而言,離線消息的獲取針對的是自己的整個離線消息,包括所有的會話(直白了說,就是上線時拉取此次離線過程中的所有未收取的離線消息)。

    離線消息的獲取是自上而下的方式(按時間序),我們的經驗是一次獲取 200 條(PS:如果離線消息過多,會分頁多次拉取,拉取1“次”可以理解為拉取1“頁”)。

    在客戶端拉取離線消息的信令中,需要帶上當前客戶端緩存的消息的最大時間戳。

    通過上節的圖我們應該知道,離線消息我們存儲的是一個線性結構(指的是按時間順序),Server 會根據這個時間戳向下查找離線消息。當重裝或者新安裝 App 時,客戶端的“當前客戶端緩存的消息的最大時間戳”可以傳 0 上來。

    Server 也會緩存客戶端拉取到的最后一條消息的時間戳,然后根據業務場景,客戶端類型等因素來決定從哪里開始拉取,如果沒有拉取完 Server 會在拉取消息的應答中帶相應的標記位,告訴客戶端繼續拉取,客戶端循環拉取,直到所有離線消息拉完。

    7.2 歷史消息拉取邏輯

    歷史消息的獲取通常針對的是單一會話。

    在拉取過程中,需要向服務端提交兩個參數:

    • 1)對方的 ID(如果是單聊的話就是對方的 UserID,如果是群則是群組ID);
    • 2)當前會話的最前面消息的時間戳(即當前會話最老一條消息的時間戳)。

    Server據這兩個參數,可以定位到這個客戶端的此會話,然后一次獲取 20 條歷史消息。

    消息的拉取時序上采用的是自下而上的方式(也就是時間序逆序),即從最后面往前翻。只要有消息,客戶端可以一直向前翻,手動觸發獲取會話的歷史消息。

    上面的拉取邏輯,在IM界面功能上通常對應的是下拉或點擊“加載更多”,比如這樣:

    8、本文小結

    本文主要分享了IM中有關離線消息和歷史消息的正確,主要包括離線消息和歷史消息的區別,以及二者在存儲、分發、拉取邏輯方面的最佳踐等。如對文中內容有異議,歡迎留言討論。

    9、參考資料

    [1] 一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)

    [2] 一套原創分布式即時通訊(IM)系統理論架構方案

    [3] 從零到卓越:京東客服即時通訊系統的技術架構演進歷程

    [4] 一套億級用戶的IM架構技術干貨(上篇):整體架構、服務拆分等

    [5] 閑魚億級IM消息系統的架構演進之路

    [6] 閑魚億級IM消息系統的可靠投遞優化實踐

    [7] 閑魚億級IM消息系統的及時性優化實踐

    [8] 基于實踐:一套百萬消息量小規模IM系統技術要點總結

    [9] IM消息送達保證機制實現(一):保證在線實時消息的可靠投遞

    [10] 理解IM消息“可靠性”和“一致性”問題,以及解決方案探討

    [11] 零基礎IM開發入門(一):什么是IM系統?

    本文同步發布于:http://www.52im.net/thread-3887-1-1.html



    作者:Jack Jiang (點擊作者姓名進入Github)
    出處:http://www.52im.net/space-uid-1.html
    交流:歡迎加入即時通訊開發交流群 215891622
    討論:http://www.52im.net/
    Jack Jiang同時是【原創Java Swing外觀工程BeautyEye】【輕量級移動端即時通訊框架MobileIMSDK】的作者,可前往下載交流。
    本博文 歡迎轉載,轉載請注明出處(也可前往 我的52im.net 找到我)。


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    Jack Jiang的 Mail: jb2011@163.com, 聯系QQ: 413980957, 微信: hellojackjiang
    主站蜘蛛池模板: 久久久亚洲裙底偷窥综合| 亚洲成人中文字幕| 亚洲精品二三区伊人久久| 2021在线观看视频精品免费| 亚洲AV无码精品色午夜果冻不卡| 你懂得的在线观看免费视频| 国产成人A人亚洲精品无码| 国产日韩AV免费无码一区二区| 亚洲熟妇av一区二区三区 | 久久亚洲AV成人无码国产最大| 大地资源二在线观看免费高清 | 成年女人看片免费视频播放器| 亚洲国产中文在线二区三区免 | 妞干网免费视频在线观看| 久久精品国产亚洲AV久| 黄a大片av永久免费| 在线观看亚洲免费视频| 国产成人精品久久亚洲| 免费一区二区三区| 亚洲不卡视频在线观看| 国产精品黄页在线播放免费| 一道本在线免费视频| 久久久久亚洲AV片无码| 国产精品永久免费10000| 亚洲偷自拍另类图片二区| 男人的天堂亚洲一区二区三区 | 德国女人一级毛片免费| 女人裸身j部免费视频无遮挡| 亚洲乱码中文字幕久久孕妇黑人 | 亚洲私人无码综合久久网| jizzjizz亚洲| 蜜桃成人无码区免费视频网站 | 一级黄色片免费观看| 亚洲欧洲日产国产综合网| 成人黄动漫画免费网站视频| 成人免费夜片在线观看| 亚洲天堂在线播放| 国产麻豆免费观看91| 色欲A∨无码蜜臀AV免费播| 亚洲av永久无码精品秋霞电影秋| 亚洲美女又黄又爽在线观看|