1.如何防止消息丢失
- Kakfa本身配置层面
- replication.factor 默认值1
创建kafka的topic时,设置副本数,根据broker数量设置,通常设置成3 - min.insync.replicas 默认值1
消息至少要被多少个副本落盘成功才返回ack给生成者,小于replication.factor的值,当request.required.acks = all时生效
- Kafka生产者层面
- 添加发送消息,成功和失败的回调处理逻辑。
- request.required.acks 设置成1 或 all
- 设置重试次数
retries 默认是0,不重试
- Kafka消费者层面
- 修改成手动提交,默认是自动提交。
enable-auto-commit: false
- 手动提交offset
使用kafka的Consumer的方法commitSync()提交
或者
spring-kafka的Acknowledgment类,用方法ack.acknowledge()提交(推荐使用)
2.如何防止重复消费
Producer生产者
如果生产者发完消息后,因为网络抖动,没有收到ack,但实际上broker已经收到了,此时生产会进行重试,于是broker就会收到多条相同的消息,而造成消费者重复消费
- 设置幂等性参数
Kafka的幂等性就是为了避免出现生产者重试的时候出现重复写入消息的情况。
开启幂等性功能配置(该配置默认为false
)如下
prop.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG,true);
- 关闭重试
会造成丢消息(不建议)
Consumer消费方
- 解决非幂等性消费问题
幂等性:多次访问的结果时一样的。对于rest的请求(get(幂等)、post(非幂等)、put(幂等),delete(幂等))
- 将消费的消息在消费方保存,进行检查时候已消费
解决方法:可以针对消息生成md5等保存在mysql(唯一索引)或者redis里面,在处理之前去mysql或者redis里面判断是否已经消费过。这个也是幂等性的思想
- rebalance问题
默认情况下,消费完消息会提交offset给kafka,避免消费,
场景1:当consumer消费完消息,但是没有返回offset时,Consumser挂了,触发rebalance,则会出现重复消费
场景2:当一个消费组在消耗一个poll到的消息时,超过了设定的poll的间隔时间,则kafka会剔除此消费者