面试篇-一眼学会解决Kafka出现堆积

90 阅读3分钟

堆积概念

所谓的Kafka消费堆积,大多数人都只是认为:Kafka生产者生产消息的速率太快,消费者消费速率太慢(即 生产 > 消费),从而出现了消息堆积。 但是在工作的过程中,我发现还存在一种情况,会导致堆积的问题,就是消费者虽然已经消费到了消息,但是一直没有提交确认。那么在这个时候,broker就会认为没有消费到,因此对应的offset没有移动,并且Lag数量会变多(这里的Lag可以理解为堆积的消息量,如果等于0的情况下,说明没有堆积)。这种情况就是“假性堆积

方案

在明白了消息堆积的概念后,我们也就知道了堆积的原因了:

  1. 生产太快,消费过慢(生产 >>> 消费)
  2. 假性堆积: 消费者消费成功之后,没有提交确认,broker认为没有消费,出现堆积

针对原因1,我们的方案主要有以下几种:

  1. 控制生产速率,减少生产量。但是这个方案是在没有影响业务的前提下,才可以进行操作。 比如我记得我在工作的时候, 有一个diff的操作,就是需要保证2个接口的数据响应是一致的。这时候我采用的是异步diff方式(通过kafka,消息中携带了新接口的参数以及老接口的响应,然后消费者调用新接口,并且用新响应和旧响应进行比较,上报diff结果)。并且有一个灰度的apollo开关,用于判断是否需要进行异步diff。在代码上线之后,通过监控发现了出现堆积,后面我先第一时间将apollo开关关掉,从而减少了生产量,并且也没有影响业务,因为返回的依旧是老接口的响应。但是控制生产量之后,堆积的消息还是在broker中,需要等待多久才可以消费完呢?所以就有了方案2.
  2. 提高消费效率。一种最简单的方式增加分区的数量,从而提高消费并发度。但是这个也是不全面的,**增加分区数量可行的前提,是需要保证分区数量 <= 消费者组中的消费数量。如果分区数量 > 消费者组中的消费者数量,那么即使再怎么加分区,消费速率依旧是没有办法提高的,此时需要对机器进行扩容,从而增加这个消费者组中消费者的数量**。如果方案2还是没有办法解决消息堆积的问题,那么可以尝试下方案3.
  3. 查看代码逻辑,判断消费者的哪一块逻辑比较满。针对这块逻辑进行优化。这时候,就可以使用Arthas中的trace命令进行排查这个消费链路中,哪块逻辑消费慢。针对这个逻辑进行优化。

针对原因2,我们的方案无非是修改消费逻辑,使得他是手动提交确认,前提需要修改enable.auto.commit=false。如果没有的话,默认是true,即手动提交确认,那么这时候即使是消费失败了,也被提交了确认,broker是没有办法确定是消费成功了还是失败了的。 但是一旦我们修改手动提交确认上线之后,又会带来一个问题:消费重复。 我记得我在工作中,也是又遇到了“假性堆积”的情况, 后面通过手动提交确认,得以解决。但是确实会带来消费重复的情况, 所幸的是,我们的消费逻辑保证了消费幂等。因此,针对消费重复的问题,必须要考虑消费幂等的方案,否则后果将不勘设想。

我是程序员阿林,觉得对你有帮助的话,可以移步我的公众号,日常更新工作中遇到的问题,并进行分享哦。

image.png