实战案例:Kafka消费组频繁rebalance导致消费堆积

819 阅读3分钟

现象

某天线上持续告警消费堆积,从量级上看当天与之前并无太大区别,遂排除。

接着,从 kafka manager 看,该 topic 有 3 个分区,尾数 139 的 ip 消费了两个分区,尾数140 和 143 的 ip 来回变换的消费 2 号分区,消费进度没有任何变化。

image.png

image.png

从 broker 端日志看,该消费组在频繁的进行 rebalance:

image.png

根据经验,kafka 频繁 rebalance 一般是消费端无法及时消费导致,而控制消费端消费速度的参数有:max.poll.recordsmax.poll.interval.ms 等。

接着,我们排查消费端代码配置:

max.poll.records = 30
max.poll.interval.ms = 1000

以上配置表面的意思是:消费端一次性最多拉取 30 条消息,两次拉取的最长时间间隔为 1 秒。

换句话说,消费者拉取的 30 条消息必须在 1 秒内处理完成,紧接着拉取下一批消息。否则,超过 1 秒后,kafka broker 会认为该消费者处理太缓慢而将他踢出消费组,从而导致消费组 rebalance。

根据 kafka 机制,消费组 rebalance 过程中是不会消费消息,所以看到 ip 是 140 和 143 轮流拉取消息,又轮流被踢出消费组,消费组循环进行 rebalance,消费就堆积了。

解决方案

调整参数:

  1. 减小 max.poll.records
  2. 或者 增加 max.poll.interval.ms

具体调整根据业务特性来选择,这里我们将 interval 间隔设置成 10s,重启服务解决:

image.png

image.png

小结

Kafka Rebalance 发生的时机

通常情况下,发生 rebalance 存在以下三种时机:

  • 组成员数量发生变化(新加消费者、删除消费者、消费者重启、消费超时等)
  • 订阅主题数量发生变化
  • 订阅主题的分区数发生变化

从接触生产上多次 kafka 消息堆积的情况来看,大多数情况都是【组员成员发生变化】而导致的 rebalance,而此过程中,又以【消费超时】情况最多,因此,当出现 rebalance 情况时,可先排查该场景。

consumer 客户端相关参数

session.timeout.ms

这个参数主要用于设置服务器等待消费者心跳的超时,超过设定值没有收到消费者的心跳,就会触发 Rebalance。

如果网络环境不佳,或者消费者处理逻辑复杂,需要适当提高这个值。

比如,broker 服务端设置了 group.min.session.timeout.ms = 6000、group.max.session.timeout.ms = 300000,所以客户端 session.timeout.ms 的值必须介于两者之间。

heartbeat.interval.ms

这个参数主要用于设置消费者向 Kafka 服务器发送心跳的频率,这个频率在 session.timeout.ms 的基础上设定。

如果这个值设置过大,可能导致长时间没有发送心跳导致 Rebalance。通常来说,应设置为:session.timeout.ms 的 1/3

max.poll.interval.ms

这个参数用于控制两次 poll 操作之间的最大允许延迟。重要参数。

如果设置过小,消费者处理时间如果超过这个值,就会被认为是失败的,从而触发 Rebalance。根据你的业务,如果处理逻辑可能会比较耗时,就需要适当提高这个值。

max.poll.records

这个参数用于控制单次 poll 操作的最大记录数。重要参数。

如果设置为一个大值,那么 poll 函数可能会阻塞很长时间用来等待足够数量的记录,这可能导致 consumer 无法在 session.timeout.ms 规定的时间内发送心跳,从而导致 Rebalance。如果你的业务允许,适当降低这个值可以避免此问题。