Commit cannot be completed since the group has already rebalanced and assigned the

问题场景

我们项目有个订单出库的业务,作为kafka消费者去消费商城项目给我们发的消息。
某次突然出现大批订单的出库状态没改的情况,拉日志一看,报了如下异常。

org.apache.kafka.clients.consumer.CommitFailedException: Commit cannot
be completed since the group has already rebalanced and assigned the
partitions to another member. This means that the time between
subsequent calls to poll() was longer than the configured
session.timeout.ms, which typically implies that the poll loop is
spending too much time message processing. You can address this either
by increasing the session timeout or by reducing the maximum size of
batches returned in poll() with max.poll.records.

并且一直在拉取重复的消息,导致新的消息没有消费掉

分析

kafka的Consumer 端还有一个参数,用于控制 Consumer 实际消费能力对 Rebalance 的影响,即 max.poll.interval.ms 参数。它限定了 Consumer 端应用程序两次调用 poll 方法的最大时间间隔。它的默认值是 5 分钟,表示你的 Consumer 程序如果在 5 分钟之内无法消费完 poll 方法返回的消息,那么 Consumer 会主动发起 “离开组” 的请求,此时就不会提交偏移量了,Coordinator 也会开启新一轮 Rebalance。

解决

个人发现有两种解决方式

- 使消费者poll的频率在单位时间内增大
这种方式,可以让消费者有更多发送心跳的次数,从而不让它挂。通过下面地方式来实现。

1.1 调整max.poll.records参数

调小每次poll消息的个数,从而缩短业务逻辑处理时长,最终减少下次再poll的等待时长

1.2 消费逻辑异步执行

将根据消息处理业务的service方法,放在异步线程里执行,使得每次poll到一批消息后,缩短业务逻辑处理时长,最终减少下次再poll的等待时长。

- 调整max.poll.interval.ms参数

这种方式没有实践过

后续问题

后来发现,由于改成了异步,业务上出现了并发问题。

场景是,收到消息后多个线程会同时去远程调用库存服务,导致库存服务插入重复的订单库存流水。

原因是,虽然分区只有一个,订阅的消费者(此时为feign调用方)也只有一个,但是被调用方有3个节点,所以小概率下会同时调用3个节点,而每个节点的逻辑是先判断有没有流水,没有就插入,此时都判断没有,所以各自插入一条。

解决

由于上述问题,最终还是改为同步,只是通过max.poll.records参数调小每次poll消息的个数了。
最终订阅的消费者(此时为feign调用方)收到消息后,会等每个消息业务处理完,再处理下一个消息,因此不再出现并发问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值