背景
在测试环境的一台机子上启动了多个mq实例,某一天同事说投递到test环境的数据,可以在test4环境上查到,这让人有点担心,担心投递的数据会被别的消费。经过了解,同事提供相关的信息,投递到MQ时会返回msgid和offsetMsgId,返回如下:
[sendStatus=SEND_OK, msgId=AC13043800067DAF6ECC4AA409590002, offsetMsgId=AC1232CB0000232B000000004BB9D206, messageQueue=MessageQueue [topic=buc_supplier_order_sync, brokerName=broker-v, queueId=3]
根据msgId去查test 和test4环境,只有在test环境下可以查到,但是根据offsetMsgId查的时候,却可以在test 和test4环境上查到
问题
按照了解,msgID 和offsetMsgId应该是集群内唯一,为什么别的集群通过offsetMsgID可以查到另外一个集群的数据呢?
了解
首先针对msgId和offsetMsgID了解是什么样的存在?才能够分析原因
可以通过查看【这里转载】RocketMQ msgId与offsetMsgId释疑(实战篇)_中间件兴趣圈-CSDN博客_offsetmsgid与messageid了解。
msgId:该ID 是消息发送者在消息发送时会首先在客户端生成,全局唯一,在 RocketMQ 中该 ID 还有另外的一个叫法:uniqId,无不体现其全局唯一性。
offsetMsgId:消息偏移ID,该 ID 记录了消息所在集群的物理地址,主要包含所存储 Broker 服务器的地址( IP 与端口号)以及所在commitlog 文件的物理偏移量。
消息 Broker 服务端将消息追加到内存后会返回其物理偏移量,即在 commitlog 文件中的文件,然后会再次生成一个id,代码中虽然也叫 msgId,其实这里就是我们常说的 offsetMsgId,即记录了消息的物理偏移量,故我们重点来看一下其具体生成规则:
MessageDecoder#createMessageId
public static String createMessageId(final ByteBuffer input , final ByteBuffer addr, final long offset) { input.flip(); int msgIDLength = addr.limit() == 8 ? 16 : 28; input.limit(msgIDLength); input.put(addr); input.putLong(offset); return UtilAll.bytes2string(input.array()); } |
首先结合该方法的调用上下文,先解释一下该方法三个入参的含义:
ByteBuffer input
用来存放 offsetMsgId 的字节缓存区( NIO 相关的基础知识)
ByteBuffer addr
当前 Broker 服务器的 IP 地址与端口号,即通过解析 offsetMsgId 从而得到消息服务器的地址信息。
long offset
消息的物理偏移量。
即构成 offsetMsgId 的组成部分:Broker 服务器的 IP 与端口号、消息的物理偏移量。
温馨提示:即在 RocketMQ中,只需要提供 offsetMsgId,可用不必知道该消息所属的topic信息即可查询该条消息的内容。
分析
了解了msgID和offsetMsgId的区别,那接下来分析为什么rocketmqConsole 利用msgID在本集群才可以查到数据,而利用offsetMsgId却可以跨集群查到数据?
通过debug rocketmqConsole的源代码排查,通过在rocketmq console 传入offsetMsgID进行查询,debug到最后到了rocketmq客户端代码,可以看到,它的实现是利用解析offsetMsgID来得到broker的地址,以及相应的偏移量,通过传给对应的broker获取数据。也就是说即使不在同一个集群,只要网络可通,就可以跨集群查询得到数据返回。
那通过msgID查询会怎么样呢?
首先,通过跨集群查询是查不到数据的。具体的源码如下:
到这里,就解释说明了为什么msgID 只能在本集群rocketmqconsole查到数据 ,offsetMsgID 却能跨集群查到。因为offsetMsgID不依赖于topic,通过自己offsetMsgID自带的信息进行查询,所以即使rocketmqconsole随便选个topic 通过offsetMsgID也可以查到对应的数据。
所以在进行rocketmq console的查询时,建议用msgID来查询,会比较准确。之前担心数据会跨集群消费,也不存在。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)