融雲技術分享:解密融雲IM產品的聊天消息ID生成策略

本文來自融雲技術團隊原創分享,原文發佈於「融雲全球互聯網通訊雲」公衆號,原題《如何實現分佈式場景下惟一 ID 生成?》,即時通信網收錄時有部分改動。php

一、引言

對於IM應用來講,消息ID(或稱序列號)是個看似不起眼,但很是重要的東西之一。html

消息ID的使用貫穿了IM技術邏輯的方方面面,好比:web

1)聊天消息的順序保證;算法

2)聊天消息QoS送達保證機制時的去重;瀏覽器

3)特定聊天消息的精確查找和匹配;安全

4)聊天消息的已讀未讀處理;微信

5)聊天消息的送達回執;網絡

6)羣聊消息的擴散讀拉取標記;session

7)... ...架構

但,IM系統高度個性化的特性(設計上沒有統一的標準和思路),包括聊天消息ID的生成算法在內,每一個產品都有自已的思路和考量。

常見的消息ID生成策略有:

1)UUID:這種方法簡單直觀,能夠很好的保證惟一性,但對於技術潔癖的人來講ID長度會有點長;

2)使用時間戳長整數:這個最偷懶,用在吞吐量不大的場景下,湊活也能用,但存在重複的風險,也沒法保證分佈式下的惟一性;

3)使用twitter開源的snowflake算法:在分佈式高併發的狀況下,這也是個不錯的選擇;

4)按用戶使用獨立的ID生成空間生成順序的ID:好比微信的消息序列號生成策略就很不錯。

從某種意義上來說,消息ID的生成策略決定了IM應用層某些功能實現的難易度,好的消息ID生成策略會讓IM產品的開發越作越順,反之越作越彆扭。

本文要分享的是融雲即時通信雲產品中的聊天消息ID生成算法和策略,一個19字節的ID就能包含:時間戳、消息類型、會話ID、序列號,小ID、大用途,值得借鑑!

免責申明:本文來自融雲官方技術團隊的分享,僅用於技術交流學習和研究目的,請勿用於非法用途,文中如涉及商業祕密,請告之我處理!

特別說明:僅出於技術研究和學習目的來分享此文,並未收取任何好處,因此此文不是廣告,我也不是託。若有不妥,請告之!

學習交流:

- 即時通信/推送技術開發交流5羣:215477170[推薦]

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

(本文同步發佈於:www.52im.net/thread-2747…

二、相關文章

三、技術背景

對於一套分佈式部署的 IM 系統,要求每條消息的 ID 要保證在集羣中全局惟一且按生成時間有序排列。如何快速高效的生成消息數據的惟一 ID ,是影響系統吞吐量的關鍵因素。

那麼,融雲是如何作到生成全局惟一消息 ID 的呢?

首先須要明確下 ID 生成的核心需求:

1)全局惟一;

2)有序。

四、設計思路

融雲消息數據的惟一 ID 長度採用 80 Bit。

每 5 個 Bit ,進行一次 32 進制編碼,轉換爲一個字符,字符取值範圍是:數字 「2 ~ 9 」和字母「A ~ B」。其中,已經去掉容易形成肉眼混淆的,數字 0 和 1 (餘下可用的數字是8個),及字母 O 和 I(餘下可用的字母是24個),總可用字符就是32個(恰好可按32進制進行編碼)。

這樣,80 Bit 能夠轉換爲 16 個字符,再加上 3 個分隔符( - ),將 16 個字符分爲 4 組,最終獲得一個 19 字符的惟一 ID ,形如:「 BD8U-FCOJ-LDC5-L789 」。 這樣設計,便可以保證生成的 ID 是有序的,也能方便閱讀。

如上圖所示,80 Bit 被分爲 4 段。

1)第一段 42 Bit:用於存放時間戳,最長可表示到 2109 年,足夠開發者當前使用了。時間戳數據放在高位,能夠保證生成的惟一 ID 是按時間有序的,這個是消息 ID 必需要知足的條件。

2)第二段 12 Bit:用於存放自旋轉 ID 。咱們知道,時間戳的精度是到毫秒的,對於一套億級 IM 系統來講,同一毫秒內產生多條消息太正常不過了,這個自旋 ID 就是在給落到同一毫秒內的消息進行自增編號。12 Bit 則意味着,同一毫秒內,單臺主機中最多能夠標識 4096( 2 的 12 次方)條消息。

3)第三段 4 Bit:用於標識會話類型。4 Bit ,最多能夠標識 16 中會話,足夠涵蓋單聊、羣聊、系統消息、聊天室、客服及公衆號等經常使用會話類型。

4)第四段 22 Bit:會話 ID 。如羣聊中的羣 ID ,聊天室中的聊天室 ID 等。與第三段會話類型組合在一塊兒,能夠惟一標識一個會話。其餘的一些 ID 生成算法,會預留兩段,分別用來標識數據中心編號和主機編號(如 SnowFlake 算法),咱們並無這樣作,而是將這兩段用來標識會話。這樣,ID 生成能夠直接融入到業務服務中,且沒必要關心服務所在的主機,作到無狀態擴縮容。

五、代碼實現

消息 ID 共佔 80 Bit ,計算時咱們分爲兩部分,高 64 Bit (記爲 highBits)和低 16 Bit (記爲 lowBits)。

具體的代碼實現過程,大體以下。

1)獲取當前系統的時間戳,並賦值給消息 ID 的高 64 Bit :

2)獲取一個自旋 ID , highBits 左移 12 位,並將自旋 ID 拼接到低 12 位中:

其中,自旋 ID 是一個從 0 到 4095 範圍內,順序遞增的數,生成規則以下:

3)上步的 highBits 左移 4 位,將會話類型拼接到低 4 位:

4)取會話 ID 哈希值的低 22 位,記爲 sessionIdInt:

5)highBits 左移 6 位,並將 sessionIdInt 的高 6 位拼接到 highBits 的低 6 位中:

6)取會話 ID 的低 16 位做爲 lowBits:

7)highBits 與 lowBits 拼接獲得 80 Bit 的消息 ID,對其進行 32 進制編碼,便可獲得惟一消息 ID:

編碼規則:從左至右,每 5 個 Bit 轉換爲一個整數,以這個整數做爲下標,便可在下表中找到對應的字符。

六、實際應用

PS:若是感受上面兩節介紹的算法思路和代碼實現有點抽象,能夠直接去看融雲的IM產品中的實際消息ID生成狀況。

好比,從融雲的Demo產品中取出的同一個用戶相近時間內的3條單聊消息ID樣本:

BD8U-DG1U-5UI5-L789

BD8U-DU6D-2205-L789

BD8U-FCOJ-LDC5-L789

好比,能夠直接登錄融雲的Web產品 web.sealtalk.im,在瀏覽器端研究學習它的消息ID生成狀況:

特別說明:僅僅出於技術研究和學習目的來分享此文,並無收到融雲的任何好處,因此此文不是廣告,我也不是託。若有不妥,請告之!

七、注意事項

融雲所使用的這種 ID 生成的方式,須要注意:

1)注意保證自旋 ID 的生成是線程安全的;

2)避免在併發狀況下,生成出一樣的 ID ;

3)此 ID 生成算法,強烈依賴系統時間,若是系統時間被改小,也可能形成 ID 生成重複。

附錄:更多IM開發熱門技術文章

新手入門一篇就夠:從零開發移動端IM
移動端IM開發者必讀(一):通俗易懂,理解移動網絡的「弱」和「慢」
移動端IM開發者必讀(二):史上最全移動弱網絡優化方法總結
從客戶端的角度來談談移動端IM的消息可靠性和送達機制
現代移動端網絡短鏈接的優化手段總結:請求速度、弱網適應、安全保障
騰訊技術分享:社交網絡圖片的帶寬壓縮技術演進之路
小白必讀:閒話HTTP短鏈接中的Session和Token
IM開發基礎知識補課:正確理解前置HTTP SSO單點登錄接口的原理
移動端IM中大規模羣消息的推送如何保證效率、實時性?
移動端IM開發須要面對的技術問題
開發IM是本身設計協議用字節流好仍是字符流好?
請問有人知道語音留言聊天的主流實現方式嗎?
IM消息送達保證機制實現(一):保證在線實時消息的可靠投遞
IM消息送達保證機制實現(二):保證離線消息的可靠投遞
如何保證IM實時消息的「時序性」與「一致性」?
一個低成本確保IM消息時序的方法探討
IM單聊和羣聊中的在線狀態同步應該用「推」仍是「拉」?
IM羣聊消息如此複雜,如何保證不丟不重?
談談移動端 IM 開發中登陸請求的優化
移動端IM登陸時拉取數據如何做到省流量?
淺談移動端IM的多點登錄和消息漫遊原理
徹底自已開發的IM該如何設計「失敗重試」機制?
通俗易懂:基於集羣的移動端IM接入層負載均衡方案分享
微信對網絡影響的技術試驗及分析(論文全文)
即時通信系統的原理、技術和應用(技術論文)
開源IM工程「蘑菇街TeamTalk」的現狀:一場虎頭蛇尾的開源秀
騰訊原創分享(一):如何大幅提高移動網絡下手機QQ的圖片傳輸速度和成功率
如約而至:微信自用的移動端IM網絡層跨平臺組件庫Mars已正式開源
基於社交網絡的Yelp是如何實現海量用戶圖片的無損壓縮的?
騰訊技術分享:騰訊是如何大幅下降帶寬和網絡流量的(圖片壓縮篇)
騰訊技術分享:騰訊是如何大幅下降帶寬和網絡流量的(音視頻技術篇)
字符編碼那點事:快速理解ASCII、Unicode、GBK和UTF-8
全面掌握移動端主流圖片格式的特色、性能、調優等
子彈短信光鮮的背後:網易雲信首席架構師分享億級IM平臺的技術實踐
IM開發基礎知識補課(五):通俗易懂,正確理解並用好MQ消息隊列
微信技術分享:微信的海量IM聊天消息序列號生成實踐(算法原理篇)
自已開發IM有那麼難嗎?手把手教你自擼一個Andriod版簡易IM (有源碼)
融雲技術分享:解密融雲IM產品的聊天消息ID生成策略
>> 更多同類文章 ……

(本文同步發佈於:www.52im.net/thread-2747…

相關文章
相關標籤/搜索