Kafka故障时如何保证已发送的消息不会丢失?
Kafka故障场景下的消息风险与防丢失方案
故障发生时已发送消息的常见问题
- 未收到Broker ACK的消息直接丢失:如果消息发出后还没拿到Broker的成功确认就触发故障,没有配置重试的生产者会直接丢失这部分消息,且感知不到发送失败
- PageCache未刷盘的消息丢失:Kafka收到消息后会先写入操作系统PageCache,默认不会立即落盘,此时如果Broker崩溃甚至机器掉电,PageCache中还没持久化到磁盘的消息会全部丢失
- 未完成副本同步的消息丢失:消息已经写入Leader副本,但还没同步到ISR列表中的所有Follower副本时Leader宕机,未同步到消息的Follower被选为新Leader,这部分未同步的消息会直接丢失
- 未提交位移的消息重复消费:消费者已经拉取到消息但还没提交消费位移就遇到Kafka故障,集群恢复后消费者会从上一次提交的位移位置重新拉取消息,造成重复消费
避免消息丢失的配置方案
生产者侧配置
- 开启重试机制:设置
retries = Integer.MAX_VALUE,配合retry.backoff.ms调整重试间隔,避免短时间频繁重试压垮集群 - 调整ACK确认级别:设置
acks = all,要求消息被ISR列表中所有副本确认后才返回发送成功,保证消息至少被多个副本接收 - 开启幂等性:设置
enable.idempotence = true,避免重试导致的消息重复问题 - 新增发送失败本地缓存逻辑:发送失败的消息可以先写入本地磁盘缓存,等Kafka集群恢复后再重发,避免瞬时故障导致消息直接丢弃
Broker侧配置
- 配置合理的副本数:Topic副本数最少设为3,保证单节点故障时还有其他副本保留完整消息
- 限制ISR最小同步副本数:3副本场景下设置
min.insync.replicas = 2,ISR列表同步副本数不足时生产者直接收到发送失败通知,避免消息只存在于单个Leader副本 - 关闭非同步副本选举:设置
unclean.leader.election.enable = false,禁止ISR列表外的副本被选为Leader,避免新Leader缺少历史消息导致数据丢失 - 按需调整刷盘策略:可通过
log.flush.interval.messages和log.flush.interval.ms控制刷盘频率,注意频繁刷盘会显著降低集群性能,常规生产环境依赖操作系统刷盘+多副本冗余即可满足可靠性要求
消费者侧配置
- 关闭自动位移提交:设置
enable.auto.commit = false,等业务逻辑处理完消息后再手动提交位移,避免消息未处理完就提交位移,消费者崩溃时消息丢失 - 消费逻辑实现幂等性:即使出现重复消费的场景,也不会造成业务数据错误
内容的提问来源于stack exchange,提问作者Nagihan Sevgi
相关产品推荐
相关产品推荐

