rocketMq - tag不一致造成的假象

概述

    这篇文章是以同事在实际工作中遇到的问题作为分析的切入点,加深自己对mq的掌握,践行“干中学”的团队理念。

    当自己差不多把基本概念都掌握的差不多的时候,必须需要实际的案例或者实践来提深自己的深度,这个时候just do it 变得很重要,所以我喜欢不停的被人挑战,截止目前帮人解答的问题包括:client端消息堆积问题、批量消息拉取问题中遇到的神奇的数字32、以及本篇的tag不一致造成的假象,也就说会有3篇文章输出。

    整个mq的问题解决文章会收录在mq的另外一个《rocketMq干中学》专题当中,欢迎订阅,欢迎挑战。


背景

    某次线上发布升级mq的消费端修改订阅的topic对应的tags,为了保证稳定性,采取了灰度发布策略,也就说发布一台服务后观察一段时间看是否正常再全量发布。

    升级的内容为consumer订阅的tags信息,灰度一台之后存在同一个consumeGroup下有多个consumer,且其中一个consumer的topic的tags信息和其他consumer不一致。

    如我们在consumeGroupA下有3个consumer,一开始3个consumer订阅了topicA + tagA||tagB,然后我们升级一个consumer订阅topicA+tagC,这个时候在同一个consumeGroup下针对同一个topic会有两个不同的订阅信息。

    升级以后的现象是什么呢,重要的事情说3遍,说3遍,说3遍。

    升级后我们发现所有的consumer都没有消费数据的记录!

     升级后我们发现所有的consumer都没有消费数据的记录! 

    升级后我们发现所有的consumer都没有消费数据的记录!


复现

    请按照以下顺序进行复现操作

        1、启动consumeA,负责订阅orderTopic,tags为A||D;

        2、等待一段时间,待consumeA启动完成;

        3、producer发送消息,发现consumeA正常消费消息;

        4、启动consumeB,负责订阅orderTopic,tags为F;

        5、producet发送消息,发现consumeA和consumerB都没有消费记录;

        6、理论上这个时候consumeA应该能够消费(tags一致),但是事实上却没有。


img_5713011cba26f8dfcbd706adc0887874.png
consumerA


img_6303ed1fd2f2364505d7171dada76b99.png
consumerB


img_d7542b22176531b03a299cfae2ff78e6.png
producer


原因分析

    在复现问题以后,基本上你知道离定位问题就不远了,其实对于经常出现的问题你只要静下心去排查问题就不大了,

我的问题排查理念:

    1、对mq在订阅topic的过程和消息拉取的过程在心里要有一个宏观的理解,说白了在心里面要清楚整个交互过程,看整个交互过程中是不是可能本身就存在这个逻辑缺陷。

    2、在原来日志不能够帮助定位你的问题的时候,在可以获取源码的时候增加日志,增加在怀疑的执行路径上。


我的问题排查过程:

    1、排查rocketMq订阅消息的逻辑

    2、排查rocketMq订阅关系同步的逻辑


订阅过程-client端:


img_e04736554220bd3a09704c3c22c97115.png
消息订阅及心跳发送

说明:

    1、在consumer端订阅的时候我们会在本地保存一个订阅数据,在这个订阅数据里面有一个字段非常重要,就是用时间戳来代表的订阅消息版本信息。


img_b27cbd7ec672df85f411ea7917fdce41.png

说明:

    1、定时通过心跳信息发送订阅数据到broker,也就是说我们会把订阅信息多次发送。

    2、定时同步broker的订阅信息到client端,也就是最终都会拷贝到一份最新的订阅信息。


img_71a0ac73b72800403945c0894f067c8d.png
订阅信息数据结构

说明:

    1、在我们创建SubscriptionData的时候我们其实用时间戳代表了版本号,这个东西非常重要,因为在broker端我们会通过版本号来区分最新数据。


订阅过程-broker端
img_40d032de7abf236656c99653fb316834.png
broker端处理过程-1

说明

    broker端处理的入口函数,相当于接收consumer的心跳数据的处理函数。


img_882b2883e58e18737fe804031b9dba22.png
broker端处理过程-2

说明:

    核心关键点,我们每次只会用最新版本号的订阅数据。


消息拉取-server端
img_9c97984183da83cf2f5e6eb8b17eb30c.png
broker端处理数据拉取

说明

    在broker端进行消费的时候我们会根据subscriptionData来判断这个消息是否属于tag内的消息,如果不是指定tag的消息,就返回false直接过滤消息。


消息拉取-client端
img_9583d8cfa22d282801ecff76494bf478.png
client端处理数据拉取

说明

    client端也做了类似的过滤,不知道是处于什么考虑,但是broker端已经对消息进行了过滤。


结论

    1、同一个consumeGroup下面的多个client定时向broker发送心跳信息,汇报自己最新的subscription信息,broker端在收到消息后以最新版本的订阅消息为准。  

    2、broker端在收到client拉取消息的请求后,会从broker的store中获取消息数据并以subscription信息去进行过滤,这个是关键的地方,broker在获取数据的时候会用最新的subscription去进行过滤。

    3、我们这个现象原因就是旧的subscription(tag为A||D)信息和新的subscription(tag为F)信息不一致,我们以最新的subscription(tag为F)为准,这个时候即便你发送的消息tag为A||D,在消息消费的会因为最新的subscription(tag为F)被过滤掉。


其他辅助信息

在消费数据的时候会不停的打印错误日志:NO_MATCHED_MSG

img_be4ded30d62709ec99ba820ccdbbdc73.png
心跳信息
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值