Kafka生产消费数据丢失和优化小结

我们经常会遇到kafka数据丢失的问题,所以将遇到过的或有可能造成数据丢失的问题进行个小总结。

其实在kafka处理数据的流程有很多,把这些流程梳理一遍,有助于分析数据丢失的情况,从这个图中可以看出数据流向,图中涉及的所以过程都可能造成数据的丢失。
在这里插入图片描述

  1. 首先要确定是否有业务数据写入
  2. 再明确数据是在kafka之前就已经丢失还是消费端丢失数据的?
    2.1 如果是在写入端丢失数据,那么每次结果应该完全一样(在写入端没有问题的前提下)。
    2.2 如果是在消费端丢失数据,那么换个消费group重新消费,多次消费结果完全一模一样的几率很低。

生产阶段

丢失问题:若生产时是同步模式,那么消息一旦生产,就会阻塞到直到收到server端的确认。但异步模式下,消息不会立刻server端,而是在客户端的缓冲区中进行缓存,缓存到指定大小或指定时间后,再发送给server。
所以,若在异步模式下,业务已经生产了数据,但还没来得及发送给server端时,server端就crash了,并且在重传周期内,server端一直未恢复,那么此消息就会丢失。
性能问题:选择同步模式,虽然很稳妥,但是每次都需要leader再向客户端发送确认。这个会降低发送速度。但选用异步模式,虽然速度是加快了,但是无法保证准确到达,缓存的越多,到达时间会变的久一些,并且缓存越大,发送也可能会变更慢。
优化:在producer端有几个参数会控制发送大小和重传的参数。

  • batch.num.messages:每次批量发送给每个paritition消息的数量(只对 asyc 起作用)
  • request.required.acks:0 表示 producer 不需要等待 leader 的确认,1 代表需要 leader 确认写入它的本地 log 并立即确认,-1 代表所有的备份都完成后确认(只对 async 起作用)
  • queue.buffering.max.ms,默认值:5000,在 producer queue 的缓存的数据最大时间(只对 async 起作用)
  • queue.buffering.max.message,默认值:10000,producer 缓存的消息的最大数量(只对 async 起作用)
  • queue.enqueue.timeout.ms,默认值:-1,0 当 queue 满时丢掉,负值是 queue 满时 block, 正值是 queue 满时 block 相应的时间(只对 async 起作用)
  • message.send.max.retries,默认值:3,消息发送最大尝试次数。
  • retry.backoff.ms,默认值:300,每次尝试增加的额外的间隔时间。这个参数不建议在生产环境设的如此小。

broker处

  1. 即使kafka收到了消息,仍然可能丢失,因为kafka收到消息后,并不是立刻落盘,而是存在了缓存中,若在此阶段kafka异常或磁盘坏掉,那么此消息仍会丢失。
    解决:修改kafka的配置参数,调整flush到文件的时间和条数
    log.flush.interval.messages=10000
    log.flush.interval.ms=3000
  2. 单批数据的长度超过kafka的限制时,会丢失数据,报kafka.common.MessageSizeTooLargeException异常。
    message.max.bytes=20000000(broker能接收消息的最大字节数,这个值应该比消费端的fetch.message.max.bytes更小才对,否则broker就会因为消费端无法使用这个消息而挂起)
    fetch.message.max.bytes=20485760
    这条配置要符合 client的生产大小<server端可接受的大小<server端可发送的大小<client的消费大小

消费逻辑

  1. 在此阶段,会批量从server端读取数据,如果设置自动提交位移,那么有可能存在还未被业务侧读取,但offset已更新的情况,那么数据就会丢失:
    enable.auto.commit:是否自动提交位移,如果为false,则需要在程序中手动提交位移。
  2. 关于性能优化
  • 启动的消费线程数
  • fetch.max.bytes:单次拉取数据的最大字节数量
  • metadata_max_age_ms:强制进行metadata刷新的周期
  • max.poll.records:单次 poll 调用返回的最大消息数,如果处理逻辑很轻量,可以适当提高该值。但是max.poll.records条数据需要在 metadata_max_age_ms这个时间内处理完

总结如下:
在考虑性能问题时,根据数据的特点和要求,需要考虑:

  1. 是单进程还是多进程生产
  2. 是同步还是异步生产,是否需要全部副本都确认
  3. 调整batch_size的大小,适当增大batch 大小可以来减小网络IO和磁盘IO的请求
  4. 是否需要多个partiton,分区是kafka进行并行读写的单位,是提升kafka速度的关键。
  5. 是否需要几个副本,副本越多,代价就是需要更多资源,尤其是磁盘资源,需要在副本数和可靠性之间平衡
  6. 是否需要开启压缩
  7. 消费时,是否需要多进程消费

Rebalance问题
在项目中时常遇到rebalance问题,单独小结一下:
触发rebalance的条件有三种:

  1. 组成员发生变更(新 Consumer 加入组、已有 Consumer 主动离开组或已有 Consumer 崩溃了)
  2. 订阅主题数发生变更
  3. 订阅主题的分区数发生变更
    我们常遇到的就是consumer没有和server没有保持活跃,导致server认为此consumer已退出,所以需要rebalance。而此时offset还未提交,所以会有重复消费的问题。
    而没有保持活跃的原因有多种:
    1)处理的线程被kill
    2)消费者消费太慢,导致超时
    3)消费太快,导致消费者处于空poll的状态,阻塞发送心跳线程;
    以上原因都会让server认为需要rebalance。
    优化方案一个是:降低max_poll_records(默认500)或提高metadata_max_age_ms(默认5分钟强制刷新metadata)
    另一个解决方案是修改heartbeat_interval_ms(默认3秒)和metadata_max_age_ms(默认5分钟)为差不多的大小,例如将metadata_max_age_ms修改为3s
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值