[kafka] 丢消息处理总结

467 阅读2分钟

这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战

丢消息

参考:

生产者端、消费者端、kafka端,都有可能发生丢消息的情况。

生产者端

原因:

  • 网络不稳定
  • 或。。。

解决办法:

  • 监听回调事件,发送失败则重发,持续失败则需要检查发生发送失败的情况。

消费者端

消费者端丢失消息的情况可能如下:

  • pull到了某消息后,自动提交的limit过了但还没处理完,随后提交了offset的更新,再做处理;
    • 然而,在提交之后消费者崩溃了,此时本应该被消费的那个offset位置对应的消息,无法被处理。

解决办法:

  • 禁止自动提交offset,转由消费完之后手动提交offset,但这个也有一个问题就是:如果消费完了,在提交offset的时候消费者崩溃了,那么消息会被消费两次。
  • 也就是说:由于消费者端更新offset和消费并不是原子性的,在崩溃的状况下无法保证消息有且仅有消费一次,因此消费端必须保证幂等性,加上手动更新offset,才能保证消息不丢失。

kafka端

kafka丢消息的最大可能如下:

  • 前提知识:kafka的分区、多副本机制。

分区中的leader副本,在往follower副本同步时,并没有完全同步最新的消息,就挂掉了。

那么这些没有同步的消息,自然就取不到了。

解决办法:

  • 确保在所有副本中都不会有未同步最新消息的情况。

    这种解决方式是在生产者端把消息发送给所有副本,确保副本都接收到才算发送成功。

    这种解决方式需要设置:acks = all(默认acks= 1,代表leader副本接收之后就算成功)

    当然,这种方式会导致发送请求的效率下降。

    • 在ACK = all的时候,需要记得还有一个东西需要配置:min.insync.replicas = m
      • 这个变量表示,消息至少要被写入到m个副本,才可以给生产者返回发送成功。
    • 同时,还有一个变量和这个有关:replication.factor= 3
      • 这个变量表示每个分区的副本数。为了保证kafka的健壮性,分区副本数必须大于上面配置的最小写入分区数,否则只要有副本挂了,就会导致中间件无法写入消息。
  • 确保没有最新消息的副本,在leader宕机后的选举中不会被选为新leader。

    这个解决方案需要配置unclean.leader.election.enable = false