RocketMq多个topic不能共用一个group,否则会造成消息丢失
问题
背景
目前新版本要上线,修改的部分地方恰好是mq消费者接收到消息后要处理的逻辑,生产灰度两套环境版本不同,生产就代码版本为1,灰度新代码版本为2,业务流量在生产。两套环境共用一个topic和tag会导致灰度环境【部署后】【切量前】这个节点是需要【线上测试】的时候部分业务流量走到灰度环境(新代码),新代码如果有问题就会影响服务不可用造成损失,所以mq中生产环境和灰度环境需要隔离。
前置条件
生产四个消费者,灰度四个消费者
灰度
更改前配置
topic=topic1
consumergroup=consumergroup1
tag=tag1
考虑到业务流量在生产,在不影响生产环境的情况下,只修改topic,生产灰度各自一个topic,但消费者组相同,然后重启灰度环境的四台消费者
更改后配置
topic=topic2
consumergroup=consumergroup1
tag=tag1
重启灰度四台消费者
情况
重启后,业务流量在生产,跟踪业务链路发现mq消息丢失,为了复现线上的情况,进行了线下模拟。
模拟
消费者consumer1配置
topic=local_tiger-web_bill_topic
consumergroup=local_tiger-web_bill_invoice_group
tag=bill_invoice_tag
消费者consumer2配置
topic=tiger_test_mq_topic
consumergroup=local_tiger-web_bill_invoice_group
tag=bill_invoice_tag
1.按照如上配置启动consumer1,consumer2 发现以下情形
topic=local_tiger-web_bill_topic

topic=tiger_test_mq_topic

2.发送消息至local_tiger-web_bill_topic,会发现有消息丢失


原理
两台客户端属于同一个消费者组
consumer负载均衡逻中会查找该消费者组下的客户端集合而不是该topic下的客户端
org.apache.rocketmq.client.impl.factory.MQClientInstance#findConsumerIdList

在获取到topic下的消息队列后将消息队列集合和客户端集合做一个分配
org.apache.rocketmq.client.consumer.rebalance.AllocateMessageQueueAveragely#allocate

该负载是一个默认的负载策略,这个方法会返回当前客户端所被分配的消息队列
原因
经过debug发现
consumer1中topic为local_tiger-web_bill_topic,消费者组为local_tiger-web_bill_invoice_group
这台启动进行负载均衡时获取到该topic的16个消息队列,获取到该消费者组的2台客户端
在平均分配策略中分配时因为有两台机器,所以这台机器只分配了8个消息队列,另外8个消息队列等待另一台客户端进行负载均衡时进行分配
consumer2中topic为tiger_test_mq_topic,消费者组为local_tiger-web_bill_invoice_group
但是在这台启动进行负载均衡时获取不到topic=local_tiger-web_bill_topic,所以另外8个消息队列就没有被分配出去
同理tiger_test_mq_topic的另外8个消息队列也没有被分配出去,所以造成了以下这种局面
topic=local_tiger-web_bill_topic

topic=tiger_test_mq_topic

结论
当环境需要隔离时topic和group全部更换,多个topic不共用一个group
更多推荐

所有评论(0)