當咱們用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。ui
下面就來介紹一下這兩個ID的生成算法:編碼
msgId: 3d
如下是RocketMQ部分源碼的節選blog
初始化參數LEN,FIX_STRING,COUNTER進程
初始化bufferip
設置開始時間get
字節轉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的思路?若是文章有什麼不理解的地方歡迎你們提出寶貴的意見,也歡迎你們多多交流~~~~