RocketMQ生产环境主题扩分片后遇到的坑

简介: RocketMQ生产环境主题扩分片后遇到的坑

消息组接到某项目组反馈,topic 在扩容后出现部分队列无法被消费者,导致消息积压,影响线上业务?


考虑到该问题是发送在真实的线上环境,为了避免泄密,本文先在的虚拟机中来重现问题。


1、案情回顾


1.1 集群现状


集群信息如下:

f91fc4b6263f81a3614a2b9056798d72.png

例如业务主体名 topic_dw_test_by_order_01 的路由信息如图所示:

eb42e711d5e157bb7a6adbb978777476.png

当前的消费者信息:

08760c080d1086f1767d24600043b03a.jpg

broker 的配置信息如下:

brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH
brokerIP1=192.168.0.220
brokerIP2-192.168.0.220
namesrvAddr=192.168.0.221:9876;192.168.0.220:9876
storePathRootDir=/opt/application/rocketmq-all-4.5.2-bin-release/store
storePathCommitLog=/opt/application/rocketmq-all-4.5.2-bin-release/store/commitlog
autoCreateTopicEnable=false
autoCreateSubscriptionGroup=false

备注:公司对 topic、消费组进行了严格的管控,项目组需要使用时需要向运维人员申请,故 broker 集群不允许自动创建主题与自动创建消费组。


由于该业务量稳步提升,项目组觉得该主题的队列数太少,不利于增加消费者来提高其消费能力,故向运维人员提出增加队列的需求。


1.2、RocketMQ 在线扩容队列


运维通过公司自研的消息运维平台,直接以指定集群的方式为 topic 扩容,该运维平台底层其实使用了RocketMQ 提供的 updateTopic 命令,其命令说明如下:

148afa6269876c15a28d66e0e565d2e1.png

从上图可以得知可以通过 -c 命令来指定在集群中所有的 broker 上创建队列,在本例中,将队列数从 4 设置为 8,具体命令如下:

sh ./mqadmin upateTopic -n 192.168.0.220:9876 -c DefaultCluster -t topic_dw_test_by_order_01 -r 8 -w 8

执行效果如图所示,表示更新成功。

a36769085cd1d0cafeefe055ecf61c30.jpg

我们再来从 rocketmq-console 中来看命令执行后的效果:

003c097c37fbe80b2f5b768df8e7dd51.png

从上图可以得知,主题的队列数已经扩容到了8个,并且在集群的两台broker上都创建了队列。


1.3 消息发送


从 RocketMQ 系列可知,RocketMQ 是支持在线 topic 在线扩容机制的,故无需重启 消息发送者、消息消费者,随着时间的推移,我们可以查看topic的所有队列都参与到了消息的负载中,如图所示:

018065091ac3578143503aa58d2c75dc.jpg

我们可以清晰的看到,所有的16个队列(每个 broker 8个队列)都参与到了消息发送的,运维小哥愉快的完成了topic的扩容。


2、问题暴露


该 topic 被 5个消费组所订阅,突然接到通知,其中有两个消费组反馈,部分队列的消息没有被消费,导致下游系统并没有及时得到处理,引起用户的注意。


3、问题分析


当时到项目组提交到消息组时,我第一反应是先看消费者的队列,打开该主题的消费情况,如图所示:


667d6733928367486fb49d6ddec24c25.jpg

发现队列数并没有积压,备注(由于生产是4主4从,每一个 broker上8个队列,故总共32个队列),当时由于比较急,并没有第一时间发现这个界面,竟然只包含一个消费者,觉得并没有消息积压,又由于同一个集群,其他消费组没有问题,只有两个消费组有问题,怀疑是应用的问题,就采取了重启,打印线程栈等方法。


事后诸葛亮:其实这完成是错误的,为什么这样说呢?因为项目组(业务方)已经告知一部分业务未处理,说明肯定有队列的消息积压,当根据自己的知识,结合看到的监控页面做出的判断与业务方反馈的出现冲突时,一定是自己的判断出了问题。


正在我们“如火如荼”的认定是项目有问题时,这时另外一个团队成员提出了一个新的观点,原来在得到业务方反馈时,他得知同一个主题,被5个消费组订阅,只有其中两个有问题,那他通过rocketmq-console来找两者的区别,找到区别,找到规律,就离解决问题的路近了。


他通过对比发现,出问题的消费组只有两个客户端在消费(通常生产环境是4节点消费),而没有出现问题的消费组只有4个进程都在处理,即发现现象:出错的消费组,并没有全员参与到消费。正如上面的图所示:只有其中一个进程在处理8个队列,另外8个队列并没有在消费。


那现在就是要分析为啥topic共有16个队列,但这里只有1个消费者队列在消费,另外一个消费者不作为?


首先根据 RocketMQ 消息队列负载机制,2个消费者,只有1个消费者在消费,并且一个有一个明显的特点是,只有 broker-a 上的队列在消费,broker-b 上的队列一个也没消费。那这两个是不是有什么规律可询?


正在思考为啥会出现这种现象时,团队中的另一个同事又在思考是不是集群是不是 broker-b (对应我们生产环境是 broker-c 、broker-d )上的队列都未消费,是不是这些队列是在新扩容的机器?扩容的时候是不是没有把订阅关系在新的集群上创建?


提出了疑问,接下来就开始验证猜想,通过查阅 broker-c、broker-d(对应我们生产环境)在我们系统中创建的时间是 2018-7月 的时候,就基本得出结论,是不是扩容时并没有在新集群上创建订阅消息,故无法消费消息,后面一查证,果然如此。


然后运维小哥,立马创建订阅组,创建方法如图所示:


492969fdbd9befd55666ef290e46c5cd.jpg

创建好消费组后,再去查看topic的消费情况时,另外一个消费组也开始处理消息了,如下图所示:

e15a002325cb53790957f723ce31258d.jpg


4、问题复盘


潜在原因:DefaultCluster 集群进行过一次集群扩容,从原来的一台消息服务器( broker-a )额外增加一台broker服务器( broker-b ),但扩容的时候并没有把原先的存在于 broker-a 上的主题、消费组扩容到 broker-b 服务器。


触发原因:接到项目组的扩容需求,将集群队列数从4个扩容到8个,这样该topic就在集群的a、b都会存在8个队列,但Broker不允许自动创建消费组(订阅关系),消费者无法从broker-b上队列上拉取消息,导致在broker-b队列上的消息堆积,无法被消费。


解决办法:运维通过命令,在broker-b上创建对应的订阅消息,问题解决。


经验教训:集群扩容时,需要同步在集群上的topic.json、subscriptionGroup.json文件。


RocketMQ 理论基础,消费者向 Broker 发起消息拉取请求时,如果broker上并没有存在该消费组的订阅消息时,如果不允许自动创建(autoCreateSubscriptionGroup 设置为 false),默认为true,则不会返回消息给客户端,其代码如下:

aee29d796d301e6a8fd4bc616465470a.jpg

问题解决后,团队内部成员也分享了一下他在本次排查问题的处理方法:寻找出现问题的规律、推断问题、 然后验证问题。规律可以是问题本身的规律  也可以是和正常对比的差。

相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
6月前
|
消息中间件 安全 物联网
MQTT常见问题之新增自定义主题后平台侧收不到发布的数据如何解决
MQTT(Message Queuing Telemetry Transport)是一个轻量级的、基于发布/订阅模式的消息协议,广泛用于物联网(IoT)中设备间的通信。以下是MQTT使用过程中可能遇到的一些常见问题及其答案的汇总:
|
6月前
|
消息中间件 弹性计算 物联网
MQTT常见问题之发布MQTT主题消息失败如何解决
MQTT(Message Queuing Telemetry Transport)是一个轻量级的、基于发布/订阅模式的消息协议,广泛用于物联网(IoT)中设备间的通信。以下是MQTT使用过程中可能遇到的一些常见问题及其答案的汇总:
|
12月前
|
传感器 物联网
详解MQTT主题和通配符
详解MQTT主题和通配符
819 0
详解MQTT主题和通配符
|
4月前
|
消息中间件 搜索推荐 RocketMQ
消息队列 MQ使用问题之如何将一个主题的多个分区分布到不同的Broker上
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
6月前
|
消息中间件 Java RocketMQ
MQ产品使用合集之在同一个 Java 进程内建立三个消费对象并设置三个消费者组订阅同一主题和标签的情况下,是否会发生其中一个消费者组无法接收到消息的现象
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
103 1
|
消息中间件 存储 缓存
RocketMQ 监控告警:生产环境如何快速通过监控预警发现堆积、收发失败等问题?
本文主要向大家介绍如何利用 RocketMQ 可观测体系中的指标监控,对生产环境中典型场景:消息堆积、消息收发失败等场景配置合理的监控预警,快速发现问题,定位问题。
1404 0
RocketMQ 监控告警:生产环境如何快速通过监控预警发现堆积、收发失败等问题?
EMQ
|
监控 安全 数据可视化
EMQX Enterprise 5.1 正式发布:生产环境就绪的 MQTT over QUIC、基于 MQTT 的文件传输支持
EMQX Enterprise 5.1 单集群可达 1 亿客户端连接;创新性地引入 MQTT over QUIC 协议;同时提供了 MQTT 大文件传输能力以及可视化数据集成能力。
EMQ
255 0
EMQX Enterprise 5.1 正式发布:生产环境就绪的 MQTT over QUIC、基于 MQTT 的文件传输支持
|
消息中间件 应用服务中间件 nginx
【RabbitMQ六】——RabbitMQ主题模式(Topic)
【RabbitMQ六】——RabbitMQ主题模式(Topic)
381 1
|
消息中间件 存储 Cloud Native
【活动】30秒上云体验,一键体验RocketMQ 六大生产环境
免费试用+30秒一键体验,低门槛、快速、高效、易操作,带你了解“历经万亿级数据洪峰考验”的云消息队列RocketMQ
551 6
|
消息中间件 存储
消息队列之RabbitMQ之主题(Topics)模式
RabbitMQ是一个消息中间件,它接受并转发消息。它有6中工作模式,而主题模式是它的核心。在主题模式中,主要是通配符的添加与使用。
270 0