RocketMQ msgId生成算法


      當我們用RocketMQ發送信息的時候通常都會返回如下信息:

      SendResult [sendStatus=SEND_OK, msgId=0A42333A0DC818B4AAC246C290FD0000, offsetMsgId=0A42333A00002A9F000000000134F1F5, messageQueue=MessageQueue [topic=topicTest1, brokerName=mac.local, queueId=3], queueOffset=4]

     對於客戶端來說msgId是由客戶端producer自己生成的,offsetMsgId是由服務端broker生成的,其中offsetMsgId就是我們在rocketMQ控制台直接輸入查詢的那個messageId。

    下面就來介紹一下這兩個ID的生成算法:

     msgId:          

     以下是RocketMQ部分源碼的節選

     

      初始化參數LEN,FIX_STRING,COUNTER

      初始化buffer

      設置開始時間

      字節轉string工具方法

 

    最終生成msgId

   

     其中createUniqId就是最終生成msgId方法。除些之外的方法者是createUniqId調用或者被間接調用的方法,這些方法實現也比較簡單。這里就不一一解釋了~

     StringBuilder sb = new StringBuilder(LEN * 2);

     由此可知msgId的長度是LEN * 2 = 16 * 2 = 32;

     設time = 當前時間 - 本月開始時間(ms);

     從代碼得到 FIX_STRING = ip + 進程pid + MessageClientIDSetter.class.getClassLoader().hashCode();

     createUniqIDBuffer 加入time 和 counter 因子。

     最終得到msgId的生成因子是:   ip + 進程pid + MessageClientIDSetter.class.getClassLoader().hashCode() + time + counter(AtomicInteger自增變量)

     最后調用bytes2string進行十六進制的移位和編碼就產生了我們的msgId。

     那我們來分析一下這個算法:

    對於每個producer實例來說ip都是唯一的,所以不同producer生成的msgId是不會重復的。對於producer單個實例來說的區分因子是:time + counter。首先應用不重啟的情況下msgId是保證唯一性的,應用重啟了只要系統的時鍾不變msgId也是唯一的。所以只要系統的時鍾不回撥我們就可以保證msgId的全局唯一。

    有人也許會說應用運行了一個月再進行重啟msgId就會重復了。從生成算法上來說是的!但是MQ的message是有時效性的,有效期是72小時也就是3天。每天的凌晨4點rocketMQ會把過期的message清除掉。所以msgId也是保證全局唯一的。

 

 offsetMsgId:

 broker端生成的offsetMsgId就比較簡單了,直接就是主機ip + 物理分區的offset,再調用UtilAll.bytes2string進行移位轉碼就完成了,是不是很簡單粗爆?!

 

      以上就是RocketMQ生成msgId和offsetMsgId的生成算法。通過閱讀文章我們除了了解RocketMQ生成msgId的方式之外,在日常項目中如果有遇到類似遇到生成全局唯一key場景時是不是也可以借鑒一下RocketMQ的思路?如果文章有什么不理解的地方歡迎大家提出寶貴的意見,也歡迎大家多多交流~~~~

      


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM