如何配置Kafka无消息丢失
那么Kafka只对“已提交“的消息(committed message) 做有限度的持久化保证.
这句话里有两个核心要素.
第一核心是已提交的消息. 什么是已提交的消息? 当Kafka的若干个Broker成功地接收到一条消息并写入到日志文件后, 它会告诉生产者程序这条消息已经成功提交. 这条消息在Kafka看来就正式变为”已提交“的消息.
第二个核心是做有限度的持久化保证.也就是说Kafka不能保证在任何情况下都做到不丢失消息, 其实就是说Kafka的不丢消息是有前提的.. 假如你的消息是保存在N个Kafka Broker上, 那么这个前提条件就是这N个Broker中至少有一个存活.
消息丢失案例
案例1: 生产者程序丢失数据
如果调用的是 producer.send(msg)这个API, 那么它通常会立即返回, 但是此时你不能认为消息已经成功发送.
这种发送方式有个有趣的名字, 叫“fire and forget”, 翻译一下就是“发射后不管”. 意思是执行完一个操作后不去管它的结果是否成功. 如果出现消息丢失, 我们是无法知晓的. 这种方式是很不靠谱的.
解决这个问题的方法非常简单: Producer永远要使用带有回调通知的发送API, 也就是说不要使用 producer.send(msg), 而是使用producer.send(msg, callback). callback(回调) 它能准确地告诉你消息是否真的提交成功了. 一旦出现消息提交失败的情况, 你就可以有针对性地进行处理.
案例2: 消费者程序丢失数据
Consumer端丢失数据主要体现在Consumer端要消费的消息不见了. Consumer程序有个位移的概念, 表示的是这个Consumer当前消费到的Topic分区的位置.
Kafka中Consumer消息丢失, 解决办法就是: 维持先消费消息(阅读), 再更新位移(书签)的顺序即可. 这样就能最大限度地保证消息不丢失. 这种处理方式可能带来的问题是消息的重复处理.
多线程异步处理消费消息, Consumer程序不要开启自动提交位移, 而是要应用程序手动提交位移.
最佳实践
- 使用producer.send(msg, callback), 带有回调通知的send方法.
- 设置acks=all. 代表所有副本Broker都要接收到消息, 该消息才算是“已提交”. 这时最高等级的已提交定义.
- 设置retries为一个较大值. 当producer发送失败时, 能够重试消息发送, 避免消息丢失.
- 设置unclean.leader.election.enable=false. 控制的是有哪些Broker有资格竞选分区的Leader. 不允许落后的Broker竞选Leader.
- 设置replication.factor>=3, 将消息多保存几份, 防止消息丢失.
- 设置min.insync.replicas>1. 控制消息至少被写入到多少副本才算是已提交.
- 确保replication.factor > min.insync.replicas. 如果两个相等, 那么只要有一个副本挂机, 整个分区就无法工作了, 推荐设置成 replication.factor = min.insync.replicas+ 1
- 确保消息消费完成后再提交. enable.auto.commit设置成false, 采用手动提交位移的方式. 这种对于单Consumer多线程处理的场景而言是至关重要的.
此文章为3月Day17学习笔记, 内容来源于极客时间《Kafka核心技术与实战》, 强烈推荐该课