Jack Jiang

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

          本文來自融云技術(shù)團(tuán)隊(duì)原創(chuàng)分享,原文發(fā)布于“融云全球互聯(lián)網(wǎng)通信云”公眾號(hào),原題《如何實(shí)現(xiàn)分布式場景下唯一 ID 生成?》,即時(shí)通訊網(wǎng)收錄時(shí)有部分改動(dòng)。

          1、引言

          對于IM應(yīng)用來說,消息ID(或稱序列號(hào))是個(gè)看似不起眼,但非常重要的東西之一。

          消息ID的使用貫穿了IM技術(shù)邏輯的方方面面,比如:

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

          2)聊天消息QoS送達(dá)保證機(jī)制時(shí)的去重;

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

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

          5)聊天消息的送達(dá)回執(zhí);

          6)群聊消息的擴(kuò)散讀拉取標(biāo)記;

          7)... ...

          但,IM系統(tǒng)高度個(gè)性化的特性(設(shè)計(jì)上沒有統(tǒng)一的標(biāo)準(zhǔn)和思路),包括聊天消息ID的生成算法在內(nèi),每個(gè)產(chǎn)品都有自已的思路和考量。

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

          1)UUID:這種方法簡單直觀,可以很好的保證唯一性,但對于技術(shù)潔癖的人來說ID長度會(huì)有點(diǎn)長;

          2)使用時(shí)間戳長整數(shù):這個(gè)最偷懶,用在吞吐量不大的場景下,湊活也能用,但存在重復(fù)的風(fēng)險(xiǎn),也無法保證分布式下的唯一性;

          3)使用twitter開源的snowflake算法:在分布式高并發(fā)的情況下,這也是個(gè)不錯(cuò)的選擇;

          4)按用戶使用獨(dú)立的ID生成空間生成順序的ID:比如微信的消息序列號(hào)生成策略就很不錯(cuò)。

          從某種意義上來講,消息ID的生成策略決定了IM應(yīng)用層某些功能實(shí)現(xiàn)的難易度,好的消息ID生成策略會(huì)讓IM產(chǎn)品的開發(fā)越做越順,反之越做越別扭。

          本文要分享的是融云即時(shí)通訊云產(chǎn)品中的聊天消息ID生成算法和策略,一個(gè)19字節(jié)的ID就能包含:時(shí)間戳、消息類型、會(huì)話ID、序列號(hào),小ID、大用途,值得借鑒!

          免責(zé)申明:本文來自融云官方技術(shù)團(tuán)隊(duì)的分享,僅用于技術(shù)交流學(xué)習(xí)和研究目的,請勿用于非法用途,文中如涉及商業(yè)秘密,請告之我處理!

          特別說明:僅出于技術(shù)研究和學(xué)習(xí)目的來分享此文,并未收取任何好處,所以此文不是廣告,我也不是托。如有不妥,請告之!

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

          - 即時(shí)通訊/推送技術(shù)開發(fā)交流5群:215477170[推薦]

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

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

          2、相關(guān)文章

          3、技術(shù)背景

          對于一套分布式部署的 IM 系統(tǒng),要求每條消息的 ID 要保證在集群中全局唯一且按生成時(shí)間有序排列。如何快速高效的生成消息數(shù)據(jù)的唯一 ID ,是影響系統(tǒng)吞吐量的關(guān)鍵因素。

          那么,融云是如何做到生成全局唯一消息 ID 的呢?

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

          1)全局唯一;

          2)有序。

          4、設(shè)計(jì)思路

          融云消息數(shù)據(jù)的唯一 ID 長度采用 80 Bit。

          每 5 個(gè) Bit ,進(jìn)行一次 32 進(jìn)制編碼,轉(zhuǎn)換為一個(gè)字符,字符取值范圍是:數(shù)字 “2 ~ 9 ”和字母“A ~ B”。其中,已經(jīng)去掉容易造成肉眼混淆的,數(shù)字 0 和 1 (余下可用的數(shù)字是8個(gè)),及字母 O 和 I(余下可用的字母是24個(gè)),總可用字符就是32個(gè)(剛好可按32進(jìn)制進(jìn)行編碼)。

          這樣,80 Bit 可以轉(zhuǎn)換為 16 個(gè)字符,再加上 3 個(gè)分隔符( - ),將 16 個(gè)字符分為 4 組,最終得到一個(gè) 19 字符的唯一 ID ,形如:“ BD8U-FCOJ-LDC5-L789 ”。 這樣設(shè)計(jì),即可以保證生成的 ID 是有序的,也能方便閱讀。

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

          1)第一段 42 Bit:用于存放時(shí)間戳,最長可表示到 2109 年,足夠開發(fā)者當(dāng)前使用了。時(shí)間戳數(shù)據(jù)放在高位,可以保證生成的唯一 ID 是按時(shí)間有序的,這個(gè)是消息 ID 必須要滿足的條件。

          2)第二段 12 Bit:用于存放自旋轉(zhuǎn) ID 。我們知道,時(shí)間戳的精度是到毫秒的,對于一套億級(jí) IM 系統(tǒng)來說,同一毫秒內(nèi)產(chǎn)生多條消息太正常不過了,這個(gè)自旋 ID 就是在給落到同一毫秒內(nèi)的消息進(jìn)行自增編號(hào)。12 Bit 則意味著,同一毫秒內(nèi),單臺(tái)主機(jī)中最多可以標(biāo)識(shí) 4096( 2 的 12 次方)條消息。

          3)第三段 4 Bit:用于標(biāo)識(shí)會(huì)話類型。4 Bit ,最多可以標(biāo)識(shí) 16 中會(huì)話,足夠涵蓋單聊、群聊、系統(tǒng)消息、聊天室、客服及公眾號(hào)等常用會(huì)話類型。

          4)第四段 22 Bit:會(huì)話 ID 。如群聊中的群 ID ,聊天室中的聊天室 ID 等。與第三段會(huì)話類型組合在一起,可以唯一標(biāo)識(shí)一個(gè)會(huì)話。其他的一些 ID 生成算法,會(huì)預(yù)留兩段,分別用來標(biāo)識(shí)數(shù)據(jù)中心編號(hào)和主機(jī)編號(hào)(如 SnowFlake 算法),我們并沒有這樣做,而是將這兩段用來標(biāo)識(shí)會(huì)話。這樣,ID 生成可以直接融入到業(yè)務(wù)服務(wù)中,且不必關(guān)心服務(wù)所在的主機(jī),做到無狀態(tài)擴(kuò)縮容。

          5、代碼實(shí)現(xiàn)

          消息 ID 共占 80 Bit ,計(jì)算時(shí)我們分為兩部分,高 64 Bit (記為 highBits)和低 16 Bit (記為 lowBits)。

          具體的代碼實(shí)現(xiàn)過程,大致如下。

          1)獲取當(dāng)前系統(tǒng)的時(shí)間戳,并賦值給消息 ID 的高 64 Bit :

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

          其中,自旋 ID 是一個(gè)從 0 到 4095 范圍內(nèi),順序遞增的數(shù),生成規(guī)則如下:

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

          4)取會(huì)話 ID 哈希值的低 22 位,記為 sessionIdInt:

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

          6)取會(huì)話 ID 的低 16 位作為 lowBits:

          7)highBits 與 lowBits 拼接得到 80 Bit 的消息 ID,對其進(jìn)行 32 進(jìn)制編碼,即可得到唯一消息 ID:

          編碼規(guī)則:從左至右,每 5 個(gè) Bit 轉(zhuǎn)換為一個(gè)整數(shù),以這個(gè)整數(shù)作為下標(biāo),即可在下表中找到對應(yīng)的字符。

          6、實(shí)際應(yīng)用

          PS:如果感覺上面兩節(jié)介紹的算法思路和代碼實(shí)現(xiàn)有點(diǎn)抽象,可以直接去看融云的IM產(chǎn)品中的實(shí)際消息ID生成情況。

          比如,從融云的Demo產(chǎn)品中取出的同一個(gè)用戶相近時(shí)間內(nèi)的3條單聊消息ID樣本:

          BD8U-DG1U-5UI5-L789

          BD8U-DU6D-2205-L789

          BD8U-FCOJ-LDC5-L789

          比如,可以直接登陸融云的Web產(chǎn)品 http://web.sealtalk.im,在瀏覽器端研究學(xué)習(xí)它的消息ID生成情況:

          特別說明:僅僅出于技術(shù)研究和學(xué)習(xí)目的來分享此文,并沒有收到融云的任何好處,所以此文不是廣告,我也不是托。如有不妥,請告之!

          7、注意事項(xiàng)

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

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

          2)避免在并發(fā)情況下,生成出同樣的 ID ;

          3)此 ID 生成算法,強(qiáng)烈依賴系統(tǒng)時(shí)間,如果系統(tǒng)時(shí)間被改小,也可能造成 ID 生成重復(fù)。

          附錄:更多IM開發(fā)熱門技術(shù)文章

          新手入門一篇就夠:從零開發(fā)移動(dòng)端IM
          移動(dòng)端IM開發(fā)者必讀(一):通俗易懂,理解移動(dòng)網(wǎng)絡(luò)的“弱”和“慢”
          移動(dòng)端IM開發(fā)者必讀(二):史上最全移動(dòng)弱網(wǎng)絡(luò)優(yōu)化方法總結(jié)
          從客戶端的角度來談?wù)勔苿?dòng)端IM的消息可靠性和送達(dá)機(jī)制
          現(xiàn)代移動(dòng)端網(wǎng)絡(luò)短連接的優(yōu)化手段總結(jié):請求速度、弱網(wǎng)適應(yīng)、安全保障
          騰訊技術(shù)分享:社交網(wǎng)絡(luò)圖片的帶寬壓縮技術(shù)演進(jìn)之路
          小白必讀:閑話HTTP短連接中的Session和Token
          IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課:正確理解前置HTTP SSO單點(diǎn)登陸接口的原理
          移動(dòng)端IM中大規(guī)模群消息的推送如何保證效率、實(shí)時(shí)性?
          移動(dòng)端IM開發(fā)需要面對的技術(shù)問題
          開發(fā)IM是自己設(shè)計(jì)協(xié)議用字節(jié)流好還是字符流好?
          請問有人知道語音留言聊天的主流實(shí)現(xiàn)方式嗎?
          IM消息送達(dá)保證機(jī)制實(shí)現(xiàn)(一):保證在線實(shí)時(shí)消息的可靠投遞
          IM消息送達(dá)保證機(jī)制實(shí)現(xiàn)(二):保證離線消息的可靠投遞
          如何保證IM實(shí)時(shí)消息的“時(shí)序性”與“一致性”?
          一個(gè)低成本確保IM消息時(shí)序的方法探討
          IM單聊和群聊中的在線狀態(tài)同步應(yīng)該用“推”還是“拉”?
          IM群聊消息如此復(fù)雜,如何保證不丟不重?
          談?wù)勔苿?dòng)端 IM 開發(fā)中登錄請求的優(yōu)化
          移動(dòng)端IM登錄時(shí)拉取數(shù)據(jù)如何作到省流量?
          淺談移動(dòng)端IM的多點(diǎn)登陸和消息漫游原理
          完全自已開發(fā)的IM該如何設(shè)計(jì)“失敗重試”機(jī)制?
          通俗易懂:基于集群的移動(dòng)端IM接入層負(fù)載均衡方案分享
          微信對網(wǎng)絡(luò)影響的技術(shù)試驗(yàn)及分析(論文全文)
          即時(shí)通訊系統(tǒng)的原理、技術(shù)和應(yīng)用(技術(shù)論文)
          開源IM工程“蘑菇街TeamTalk”的現(xiàn)狀:一場有始無終的開源秀
          騰訊原創(chuàng)分享(一):如何大幅提升移動(dòng)網(wǎng)絡(luò)下手機(jī)QQ的圖片傳輸速度和成功率
          如約而至:微信自用的移動(dòng)端IM網(wǎng)絡(luò)層跨平臺(tái)組件庫Mars已正式開源
          基于社交網(wǎng)絡(luò)的Yelp是如何實(shí)現(xiàn)海量用戶圖片的無損壓縮的?
          騰訊技術(shù)分享:騰訊是如何大幅降低帶寬和網(wǎng)絡(luò)流量的(圖片壓縮篇)
          騰訊技術(shù)分享:騰訊是如何大幅降低帶寬和網(wǎng)絡(luò)流量的(音視頻技術(shù)篇)
          字符編碼那點(diǎn)事:快速理解ASCII、Unicode、GBK和UTF-8
          全面掌握移動(dòng)端主流圖片格式的特點(diǎn)、性能、調(diào)優(yōu)等
          子彈短信光鮮的背后:網(wǎng)易云信首席架構(gòu)師分享億級(jí)IM平臺(tái)的技術(shù)實(shí)踐
          IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(五):通俗易懂,正確理解并用好MQ消息隊(duì)列
          微信技術(shù)分享:微信的海量IM聊天消息序列號(hào)生成實(shí)踐(算法原理篇)
          自已開發(fā)IM有那么難嗎?手把手教你自擼一個(gè)Andriod版簡易IM (有源碼)
          融云技術(shù)分享:解密融云IM產(chǎn)品的聊天消息ID生成策略
          >> 更多同類文章 ……

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



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


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


          網(wǎng)站導(dǎo)航:
           
          Jack Jiang的 Mail: jb2011@163.com, 聯(lián)系QQ: 413980957, 微信: hellojackjiang
          主站蜘蛛池模板: 萨嘎县| 大冶市| 连云港市| 远安县| 宜黄县| 广平县| 什邡市| 南华县| 隆化县| 玉山县| 长葛市| 荣昌县| 河池市| 册亨县| 乌鲁木齐市| 尼木县| 米林县| 吴川市| 柳州市| 临邑县| 连云港市| 司法| 房产| 治县。| 池州市| 德钦县| 怀远县| 玛多县| 武穴市| 福海县| 光泽县| 奉节县| 徐州市| 永川市| 台北县| 溧水县| 方正县| 日照市| 南溪县| 个旧市| 巴塘县|