【RocketMQ】【MsgId】MsgId 谁生成的?什么时候生成的?怎么生成的?一定唯一么?
1 前言
这节我们来看看 Rocket MQ的一个小东西,就是我们平时发消息,消息里边有个 messageId,它是全局唯一的,就好奇是谁生成的?什么时候生成的?怎么生成的?我们跟进源码看下。
我这里看的是云消息队列里的开发包哈。
2 源码分析
2.1 消息发送过程
Rocket MQ作为消息中间件,三个角度生产者、MQ、消费者,生产者制造消息发给MQ,消费者消费MQ中的消息,那么我们来看下消息的发送过程:
经过中间一系列的 send 方法,我们看最后调用的方法:
我们跟进 sendKernelImpl 看下内部发送:
可以看到 setUniqID 就是设置消息id啦。
2.2 Uniq ID 生成过程
我们继续来看看消息 ID是怎么生成的:
我们进入创建方法看看:
可以看到它是由20位的固定长度+12位的随机组成的消息ID。那我们先来看下固定长度是怎么生成的:
可以看到是静态代码块,在类加载的时候就初始化上了,是由ip+进程ID+类加载器的Hash值组成20位的固定长度。我们可以看到两个关于时间的属性:startTime、nextStartTime:
还有一个属性计数器 counter ,从0开始计数:
那我们看看 createUniqIDBuffer 的组成:
可以看到就是时间戳差+计数值来得到消息ID剩下的12位。
这样就能保证消息ID唯一么?
首先对于每个producer实例来说ip都是唯一的,所以不同producer生成的msgId是不会重复的。对于producer单个实例来说的区分因子是时间戳差和计数值。首先应用不重启的情况下msgId是保证唯一性的;应用重启了只要系统的时钟不变msgId也是唯一的。所以只要系统的时钟不回拨我们就可以保证msgId的全局唯一。有人也许会说应用运行了一个月再进行重启msgId就会重复了。从生成算法上来说是的,但是MQ的message是有时效性的,有效期是72小时也就是3天。每天的凌晨4点rocketMQ会把过期的message清除掉。所以msgId也是保证全局唯一的。
还有随机字符是时间戳+short计数值 short也就是65535个,时间戳是毫秒级,1毫秒内发送超过65535个消息的话,其实消息ID是会重复的,但是基本上1毫秒是不会这么多的吧。哈哈哈。
消息ID是谁生成的?什么时候生成的?怎么生成的?
我们看完就有结论了,是由Producer生产者发送消息的时候生成的,由20位的固定字符(ip+进程id+类加载器Hash值)+12位的(时间戳差以及计数值)来组成的。
3 小细节
批量消息发送的时候,消息ID也是这样生成的么?
是的,也都是MessageClientIDSetter.setUniqID(message); 来循环逐个生成的。
ByteBuffer是什么?可以用来干什么呢?
我们刚才可以看到 ByteBuffer.allocate,这是干什么呢?字面意思字节缓冲区,allocate()分配新的ByteBuffer。该方法需要一个参数,即缓冲区的容量。它返回分配的新的ByteBuffer。如果提供的容量为负,则抛出IllegalArgumentException。其实也就是申请一块字节为单位的固定长度的缓冲区。
byte 数组转十六进制字符串
// final static char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); public static String bytes2string(byte[] src) { char[] hexChars = new char[src.length * 2]; for (int j = 0; j < src.length; j++) { // & 过之后,byte 转成 int int v = src[j] & 0xFF; // 无符号右移 4 位,高位补 0 ,即取字节的高 4 位 hexChars[j * 2] = HEX_ARRAY[v >>> 4]; // 取字节低 4 位 hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; } return new String(hexChars); }
可以看到把一个字节拆成高4位低4位后,分别转换为字符后,装进字符数组。
那我们再想一下我们的消息ID,固定长度的生成过程 4个字节的ip + 2字节的进程ID + 4字节的hash值 = 10个字节 转换成了 20位的字符,随机字符分别是 4个字节的时间戳差 + short类型即2个字节的计数值 = 6个字节 转换成了 12位的字符。
4 小结
好啦,关于消息ID的我们就看到这里哈,有理解不对的地方欢迎指正哈。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了