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也是保证全局唯一的。
消息ID是谁生成的?什么时候生成的?怎么生成的?
我们看完就有结论了,是由Producer生产者发送消息的时候生成的,由20位的固定字符(ip+进程id+类加载器Hash值)+12位的(时间戳差以及计数值)来组成的。
3 小细节
批量消息发送的时候,消息ID也是这样生成的么?
是的,也都是MessageClientIDSetter.setUniqID(message); 来循环逐个生成的。

4 小结
好啦,关于消息ID的我们就看到这里哈,有理解不对的地方欢迎指正哈。