Kafka学习之消息丢失与消息重复消费问题分析

Kafka消息丢失

原因分析

  • Producer的ACK机制

    等级设置0或者1,可能因为没落盘或者没同步Follower导致丢失

    Producer发送消息到队列,分区Leader收到消息后返回ACK给Producer,表示接收成功,此时可以继续发送下一笔消息。

    Kafka提供了3种不同级别的ACK机制

    0:Leader收到消息后立刻返回给Producer,消息可能还没刷盘,也还没有同步给Follower。此时如果Leader挂掉,消息就丢失了。

    1:Leader将消息写入磁盘后,立刻返回ACK给Producer,消息可能还没同步Follower。此时如果Leader挂掉,选举新的Follower成为主分区,因为刚才没同步成功,所以消息丢失。

    -1:Leader将消息写入磁盘,并且同步给所有Follower,此时再返回ACK。这个方案也存在一个问题,如果在Leader准备返回ACK的时候挂掉,Producer没收到ACK认定为发送失败。此时又有2种情况

    (1)开启重试:会导致队列收到2条重复的消息,此时**需要Consumer端保证消费幂等**,后面会介绍;
    
    (2)不开启重试(不推荐):网络问题、超时等原因导致发送失败,不会重新发送,**消息容易丢失**。
    
  • Consumer设置自动提交

    消费失败来不及记录异常就宕机,但是Offset提交了,导致丢失

    Consumer进行消费时,提交Offset偏移给Kafka记录消费的最新位置。 提交Offset有以下2种方式:

    自动提交:enable.auto.commit 设置 true 开启,auto.commit.interval.ms 设置自动提交的频率间隔。Consumer获取到消息就提交Offset,不管消费是否成功

    手动提交:enable.auto.commit 设置 false ,消费完成后再调用 consumer.commit(),手动更新Offset。如果消费失败,我们可以将异常记录进行人工干预,然后再提交Offset,避免影响后面消息的消费

解决方案

  • ACK参数设置为-1

    对性能要求不是极高的情况下,建议将ACK设置-1,我们只需要在 Consumer 端结合幂等性避免消息重复消费。

Kafka消息重复消费

背景描述

  • 内容介绍

    发现每条消息处理时间长达30+秒,消息处理完后,又重新从第一条开始重复消费。

原因分析

  • Kafka异常重启

    kafka每个消息写进去,都有一个offset,代表他的序号。consumer消费数据之后,每隔一段时间,会把自己消费过的消息的offset提交一下提交到zookeeper,代表我已经消费过了。

    下次要是重启,而offset未及时提交,则会从上次消费到的offset来继续消费

    Kafka异常重启导致重复消费

  • Kafka消息消费设置时长小于实际业务执行时长

    Kafka消费者有两个配置参数:

    max.poll.interval.ms

    两次poll(拉取)操作允许的最大时间间隔。单位毫秒。默认值300000(5分钟)。

    两次poll超过此时间间隔,Kafka服务端会进行rebalance操作,导致客户端连接失效,无法提交offset信息,从而引发重复消费。

    max.poll.records

    一次poll操作获取的消息数量。默认值50。

    如果每条消息处理时间超过60秒,那么一批消息处理时间将超过5分钟,从而引发poll超时,最终导致重复消费。

解决方案

  • 幂等性处理

    可以参照博主写的这篇文章:Java并发编程学习之高并发下如何保证接口的幂等性

  • 参数优化

    1. 分析业务代码逻辑,进行性能优化,确保每条消息处理时间控制在合理范围

      每条消息的处理时间不要超过5分钟。如果超过5分钟,则考虑进行架构上的优化。

      比如A线程消费消息,放到进程内部队列中,提交offset;其他线程从内部队列取消息,并处理业务逻辑。为防止内部队列消息积压,A线程需要监控队列中消息数量,超过一定量时进入等待。

    2. 适当增大max.poll.interval.ms的值

      SpringBoot没有提供可调节此数值的参数。如果修改此数值,需要自己封装方法创建Kafka客户端:

    
      org.apache.kafka.clients.consumer.KafkaConsumer.KafkaConsumer<String,String>(Properties)
    
    
    1. 适当减小max.poll.records的值

      可通过SpringBoot配置参数"spring.kafka.consumer.max-poll-records"调整。

    
      spring:
        kafka:
          consumer:
            max-poll-records: 500
          properties:
            max:
              poll:
                interval:
                  ms: 500000
    
    

参考链接

  • 解决Kafka重复消费问题

    https://blog.youkuaiyun.com/xianyuxiaoqiang/article/details/86477976

  • Kafka配置max.poll.interval.ms参数

    https://blog.youkuaiyun.com/yuanpanni/article/details/107388269

  • Kafka消息丢失、重复消费的解决方案

    https://blog.youkuaiyun.com/qq_28834355/article/details/113663832

  • Kafka(一)Kafka的简介与架构

    https://www.cnblogs.com/frankdeng/p/9310684.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值