一次 kafka 消息堆积问题排查

2,619 阅读2分钟

收到某业务组的小伙伴发来的反馈,具体问题如下:

项目中某 kafka 消息组消费特别慢,有时候在 kafka-manager 控制台看到有些消费者已被踢出消费组。

从服务端日志看到如下信息:

该消费组在短时间内重平衡了 600 多次。

从 cat 查看得知,每条消息处理都会有 4 次数据库的交互,经过一番沟通之后,发现每条消息的处理耗时大概率保持在 200ms 以上。

Kafka 发生重平衡的有以下几种情况:

  1. 消费组成员发生变更,有新消费者加入或者离开,或者有消费者崩溃;
  2. 消费组订阅的主题数量发生变更;
  3. 消费组订阅的分区数发生变更。

在第 2、3 点都没有发生的情况下,那么就是由消费组成员发生了变化导致 Kafka 发生重平衡。

在查看 kafka 客户端日志,发现有很多如下日志:

日志的描述得知,消费者被被剔除的原因是调用 poll() 方法消费耗时太久了,其中有提到 max.poll.interval.ms 和 max.poll.records 两个参数,而且还会导致提交

max.poll.interval.ms 表示消费者处理消息逻辑的最大时间,对于某些业务来说,处理消息可能需要很长时间,比如需要 1 分钟,那么该参数就需要设置成大于 1分钟的值,否则就会被 Coordinator 剔除消息组然后重平衡, 默认值为 300000;

max.poll.records 表示每次默认拉取消息条数,默认值为 500。

我们来计算一下:

200 * 500 = 100000 < max.poll.interval.ms =300000,

前面我也讲了,当每条消息处理时间大概率会超过 200ms。

结论:

本次出现的问题是由于客户端的消息消费逻辑耗时太长,如果生产端出现消息发送增多,消费端每次都拉取了 500 条消息进行消费,这时就很容易导致消费时间过长,如果超过了 max.poll.interval.ms 所设置的时间,就会被消费组所在的 coordinator 剔除掉,从而导致重平衡,Kafka 重平衡过程中是不能消费的,会导致消费组处于类似 stop the world 的状态下,重平衡过程中也不能提交位移,这会导致消息重复消费从而使得消费组的消费速度下降,导致消息堆积。

解决办法:

根据业务逻辑调整 max.poll.records 与 max.poll.interval.ms 之间的平衡点,避免出现消费者被频繁踢出消费组导致重平衡。

更多精彩文章请关注作者维护的公众号「后端进阶」,这是一个专注后端相关技术的公众号。

关注公众号并回复「后端」免费领取后端相关电子书籍。

欢迎分享,转载请保留出处。

公众号「后端进阶」,专注后端技术分享!