【RocketMQ】记录一次RocketMQ消费延迟问题排查思路

文章目录

背景

业务团队反馈使用我提供的RocketMQ集群,上游生产的消息,部分消息,消费程序需要等1分钟,甚至几分钟后,才能收到。

问题排查

见怪不怪,大部分的问题,都是和客户端的使用上有关系,根据一番了解,业务方是这样写消费者程序的:

  1. 消费者使用拉模式;
  2. 消费者有3个实例;
  3. 使用了XXL-JOB做任务调度,每分钟执行一次,触发消费者的拉取操作
  4. XXL-JOB使用的是轮询的调度方式。

到这里,如果了解RocketMQ消费者机制的,应该已经知道问题了,下面是简单的思路总结:

  1. RocketMQ创建Topic时会有队列数的配置,类似于Kafka的Partition;
  2. 例如:RocketMQ集群有3个Broker,创建Topic时设置读队列数为16,这个Topic的总的消费队列为48;
  3. 所有消费者实例会近似平均地去负责这48个队列,也就是说,每隔1分钟,用轮询的方式去执行消费,每次只会消费到topic中1/3的消息,下一次JOB执行,才会继续消费,这中间JOB执行的间隔,就导致了消费的延迟。

下面详细说一下RocketMQ消费者的负载均衡机制。

Consumer负载均衡机制

集群模式下,同一个消费组内的消费者会分担收到的全量消息,这里的分配策略是怎样的?如果扩容消费者是否一定能提升消费能力?

Apache RocketMQ 提供了多种集群模式下的分配策略,包括平均分配策略、机房优先分配策略、一致性hash分配策略等,可以通过如下代码进行设置相应负载均衡策略。

java 复制代码
consumer.setAllocateMessageQueueStrategy(new AllocateMessageQueueAveragely());

默认的分配策略是平均分配,这也是最常见的策略。平均分配策略下消费组内的消费者会按照类似分页的策略均摊消费。

在平均分配的算法下,可以通过增加消费者的数量来提高消费的并行度。比如下图中,通过增加消费者来提高消费能力。

从一个消费者,扩到两个消费者:

从3个扩到4个:

但也不是一味地增加消费者就能提升消费能力的,比如下图中Topic的总队列数小于消费者的数量时,消费者将分配不到队列,即使消费者再多也无法提升消费能力。

在RocketMQ中每个队列都会记录自己的最小位点、最大位点。针对于消费组,还有消费位点的概念,在集群模式下,消费位点是由客户端提给交服务端保存的,在广播模式下,消费位点是由客户端自己保存的。一般情况下消费位点正常更新,不会出现消息重复,但如果消费者发生崩溃或有新的消费者加入群组,就会触发重平衡,重平衡完成后,每个消费者可能会分配到新的队列,而不是之前处理的队列。为了能继续之前的工作,消费者需要读取每个队列最后一次的提交的消费位点,然后从消费位点处继续拉取消息。但在实际执行过程中,由于客户端提交给服务端的消费位点并不是实时的,所以重平衡就可能会导致消息少量重复。

订阅关系的一致

再补充一点,也是很多业务方会忽略的一个问题,很多用户为了方便,或者不经意间,会用一个消费组去消费多个topic,这样也是会存在问题的。

同一个消费者组(Group ID相同)下所有Consumer实例所订阅的Topic与Tag及对消息的处理逻辑必须完全一致。否则,消息消费的逻辑就会混乱,甚至导致消息丢失。

相关推荐
Yan.love4 分钟前
开发场景中Java 集合的最佳选择
java·数据结构·链表
椰椰椰耶7 分钟前
【文档搜索引擎】搜索模块的完整实现
java·搜索引擎
大G哥7 分钟前
java提高正则处理效率
java·开发语言
智慧老师38 分钟前
Spring基础分析13-Spring Security框架
java·后端·spring
lxyzcm39 分钟前
C++23新特性解析:[[assume]]属性
java·c++·spring boot·c++23
V+zmm101341 小时前
基于微信小程序的乡村政务服务系统springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
Oneforlove_twoforjob2 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
xmh-sxh-13142 小时前
常用的缓存技术都有哪些
java
AiFlutter2 小时前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter
J不A秃V头A3 小时前
IntelliJ IDEA中设置激活的profile
java·intellij-idea