<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

    本文由融云技術(shù)團隊原創(chuàng)分享,原題“IM 消息數(shù)據(jù)存儲結(jié)構(gòu)設(shè)計”,內(nèi)容有修訂。

    1、引言

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

    在IM技術(shù)應(yīng)用場景越來越廣泛的前提下,對即時通訊IM技術(shù)的學(xué)習(xí)和掌握就顯的越來越有必要。

    在IM龐大的技術(shù)體系中,消息系統(tǒng)無疑是最核心的,而消息系統(tǒng)中,最關(guān)鍵的部分是消息的分發(fā)和存儲,而離線消息和歷史消息又是這個關(guān)鍵環(huán)節(jié)中不可回避的技術(shù)要點。

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

    學(xué)習(xí)交流:

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

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

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

    2、相關(guān)文章

    技術(shù)相關(guān)文章:

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

    融云技術(shù)團隊分享的其它文章:

    1. 融云安卓端IM產(chǎn)品的網(wǎng)絡(luò)鏈路?;罴夹g(shù)實踐
    2. 全面揭秘億級IM消息的可靠投遞機制
    3. 解密融云IM產(chǎn)品的聊天消息ID生成策略
    4. 萬人群聊消息投遞方案的思考和實踐
    5. 基于WebRTC的實時音視頻首幀顯示時間優(yōu)化實踐
    6. 融云IM技術(shù)分享:萬人群聊消息投遞方案的思考和實踐

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

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

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

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

    這樣實現(xiàn)的缺點就是消息不持久化,導(dǎo)致消息無法支持消息漫游,降低了消息的可靠性。

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

    而在我們設(shè)計的消息系統(tǒng)中,服務(wù)器只要接收到了發(fā)送方發(fā)上來的消息,在轉(zhuǎn)發(fā)給接收方的同時也會在離線數(shù)據(jù)庫及歷史消息庫中進行消息的落地存儲,而歷史消息的落地也就能支持消息漫游等相關(guān)功能了。

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

    關(guān)于離線消息和歷史消息,在技術(shù)上,我們是這樣定義。

    1)離線消息:

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

    以我們的系統(tǒng)經(jīng)驗來說,我們的離線消息默認(rèn)只保存最近七天的消息。

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

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

    2)歷史消息:

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

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

    以我們的系統(tǒng)經(jīng)驗來說,歷史消息的存儲時間我們設(shè)計默認(rèn)為半年,當(dāng)然這個時間可以按實際的產(chǎn)品運營規(guī)則來定,沒有硬性規(guī)定。

    5、IM消息的發(fā)送及存儲流程

    以下是我們系統(tǒng)整體的消息發(fā)送及存儲流程:

     如上圖所示:當(dāng)用戶發(fā)送聊天消息到服務(wù)器端后,首先會進入到消息系統(tǒng)中,消息系統(tǒng)會對消息進行分發(fā)以及存儲。

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

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

    在分發(fā)完消息后:消息服務(wù)會同步一份消息數(shù)據(jù)到歷史消息服務(wù)中,歷史消息服務(wù)同樣會對消息進行落地存儲。

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

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

    6.1 概述

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

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

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

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

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

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

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

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

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

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

    小結(jié)一下:

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

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

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

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

    對比擴散寫模式,擴散讀的優(yōu)點和缺點如下:

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

    6.4 小結(jié)

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

    一個優(yōu)化好的IM系統(tǒng),必須從設(shè)計上平衡讀寫壓力,避免讀或者寫任意一個維度達到天花板。

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

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

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

    7.1 離線消息拉取邏輯

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

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

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

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

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

    7.2 歷史消息拉取邏輯

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

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

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

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

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

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

    8、本文小結(jié)

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

    9、參考資料

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

    [2] 一套原創(chuàng)分布式即時通訊(IM)系統(tǒng)理論架構(gòu)方案

    [3] 從零到卓越:京東客服即時通訊系統(tǒng)的技術(shù)架構(gòu)演進歷程

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

    [5] 閑魚億級IM消息系統(tǒng)的架構(gòu)演進之路

    [6] 閑魚億級IM消息系統(tǒng)的可靠投遞優(yōu)化實踐

    [7] 閑魚億級IM消息系統(tǒng)的及時性優(yōu)化實踐

    [8] 基于實踐:一套百萬消息量小規(guī)模IM系統(tǒng)技術(shù)要點總結(jié)

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

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

    [11] 零基礎(chǔ)IM開發(fā)入門(一):什么是IM系統(tǒng)?

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



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


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


    網(wǎng)站導(dǎo)航:
     
    Jack Jiang的 Mail: jb2011@163.com, 聯(lián)系QQ: 413980957, 微信: hellojackjiang
    主站蜘蛛池模板: 午夜毛片不卡高清免费| 亚洲高清中文字幕综合网| 97碰公开在线观看免费视频| 色费女人18女人毛片免费视频| 18禁止看的免费污网站| 亚洲人成高清在线播放| 午夜两性色视频免费网站| 日本免费在线观看| jizz免费一区二区三区| 亚洲av无码av在线播放| 国产亚洲精品无码拍拍拍色欲| 97无码免费人妻超级碰碰碰碰 | 在线播放国产不卡免费视频| 亚洲国产成人99精品激情在线| 精品亚洲成AV人在线观看| 亚洲深深色噜噜狠狠爱网站| 亚洲精品视频免费观看| 日韩中文字幕免费视频| 182tv免费视频在线观看| ssswww日本免费网站片| 免费无码国产在线观国内自拍中文字幕 | 三上悠亚在线观看免费| 丝袜熟女国偷自产中文字幕亚洲| 在线成人精品国产区免费| 一级视频在线免费观看| 亚洲国产精品乱码在线观看97| 久久久久亚洲AV无码专区首| 亚洲精品乱码久久久久久久久久久久| 亚洲精品国精品久久99热| 免费播放特黄特色毛片| 亚洲阿v天堂在线2017免费| 亚欧色视频在线观看免费| 日韩精品视频在线观看免费 | 永久黄网站色视频免费| 午夜dj免费在线观看| 国产精品冒白浆免费视频 | 亚洲av日韩av无码黑人| 亚洲a在线视频视频| 91亚洲国产成人精品下载| 亚洲日韩乱码中文无码蜜桃臀| 亚洲一级黄色大片|