大厂面试真题:如何保证Kafka的消息不被重复消费
重复消费的原因
1. 客户端自动提交Offset
Kafka默认的自动提交Offset会有一个5秒钟的时间间隔,也就是消费完消息5秒钟之后在下次向broker拉取消息的时候才会提交Offset,而在这个过程中如果应用被强制Kill或者宕机的时候可能会导致Offset没有提交从而产生重复消费的问题。
2. 服务端的分区再平衡(Partition Rebalancing)
分区再平衡是指在消费者组中,当消费者实例的数目发生变化(如新的消费者加入或现有消费者离开)时,Kafka自动重新分配主题分区给消费者的过程。这个过程确保了每个消费者都能公平地分担工作负载,并在有消费者加入或离开时,能够及时调整分区的分配,从而维持系统的高可用性和负载均衡。
消费者与协调者(coordinator)之间通过心跳机制来维护其活跃状态。如果消费者在配置的max.poll.interval.ms
时间内(默认值为300000毫秒,即5分钟)没有向协调者发送心跳或请求数据,协调者会认为该消费者已经死亡,从而触发Rebalance操作。如果Consumer在Rebalance发生前没有成功提交Offset,并且在Rebalance后从之前未提交的Offset位置开始消费,会导致消息重复消费。
怎么解决重复消费
Kafka通过一系列机制来确保消息不被重复消费,这些机制涵盖了消费者配置、消费者组协调、幂等性生产者以及消息处理过程中的去重技术等。以下是Kafka保证消息不重复消费的主要方式:
1. 提高消费端的处理性能避免触发reblance
- 使用多线程方式处理消息,缩短单个消息的处理时长。
- 调整消息的超时时间。
- 减少一次性从broker上拉取数据的条数
2. 使用ConsumerRebalanceListener(再均衡监听器)
- 再均衡监听器用来设置发生再均衡动作前后的一些准备工作或者收尾工作
3. 幂等性校验
- 开启幂等性功能:prop.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, true)是在Kafka生产者的配置中进行的。这一步骤通常在创建Kafka生产者实例之前完成,用于设置生产者的行为以确保消息的幂等性。幂等性指的是对于Kafka生产者发送的相同消息(这里的“相同”指的是重试的消息,而不是内容完全相同的数据),无论发送多少次,Kafka都只会存储一条。
4. 消息去重技术
- 消息唯一标识符:在消息的生产端或消费端,可以为每条消息添加一个全局唯一的标识符(如订单ID、UUID等)。在消费消息时,消费者可以先检查该消息的唯一标识符是否已经存在于已处理的记录中,如果存在则跳过该消息,从而避免了重复消费。
- 应用程序层面的去重:在应用程序层面,可以通过维护一个已处理消息的记录或使用外部存储(如数据库、Redis等)来实现消息的去重。在消费消息前,先检查该消息是否已经被处理过,如果已经处理过,则不进行后续处理。
5. 监控和告警
- 性能监控和告警:通过监控Kafka的性能指标(如消费者的消费速度、偏移量提交情况、Kafka队列大小等)和设置告警阈值,可以及时发现和处理潜在的重复消费问题。当达到告警阈值时,可以通过短信、邮件等方式及时通知相关人员进行处理。