Skip to content

P96 Kafka 消息丢失的场景及解决方案 ​

面试题:Kafka 消息在哪些环节会丢?怎么保证不丢?

1. 三个环节的丢失场景 ​

① 生产端丢 ​

  • acks=0:发出去不管,网络失败/服务端没收到就丢;
  • acks=1:Leader 收到即确认,Leader 还没同步给副本就挂了 → 丢;
  • 发送失败没重试。

② 服务端(Broker)丢 ​

  • 副本数 = 1(没副本),节点挂了数据就丢;
  • min.insync.replicas 配置不当:Leader 接收消息后 ISR 里没有其他副本,Leader 挂了数据丢;
  • 磁盘故障、日志清理配置错误。

③ 消费端丢 ​

  • 先提交 offset 再处理业务:处理失败但 offset 已提交 → 消息被跳过(丢);
  • 自动提交(enable.auto.commit=true)且处理耗时 > 提交间隔 → 处理中挂了,offset 已提交;
  • 消费者异常退出导致再均衡,未处理完的消息丢失。

2. 解决方案 ​

生产端 ​

text
acks = all(或 -1)
retries 设置较大(如 3+)
enable.idempotence = true(幂等生产者,配合 acks=all)

服务端 ​

text
replication.factor >= 3(副本数)
min.insync.replicas >= 2(ISR 最小副本数)
unclean.leader.election.enable = false(不允许非同步副本当选 Leader)

消费端 ​

java
// 手动提交 offset:处理成功后再提交
props.put("enable.auto.commit", "false");

// 消费循环里
ConsumerRecords records = consumer.poll(...);
process(records);              // 先处理
consumer.commitSync();         // 再提交

3. 至少一次 vs 精确一次 ​

  • 上面配置保证 At Least Once(至少一次),可能重复消费;
  • 要 Exactly Once:幂等生产者 + 事务(initTransactions / beginTransaction / 消费-处理-提交事务);
  • 或者消费端幂等(业务唯一键去重)。

4. 加分点 ​

  • 完整答法:生产 acks=all + 重试 + 幂等,服务端多副本 + min.insync,消费端先处理后提交 + 幂等;
  • 追问"ack 和 ISR 的关系":acks=all 是等 ISR 全部确认;
  • 提到"顺序保证"与"分区数变化"时可能乱序;
  • 事故排查:看日志 Offset commit、Leader 变更、生产端异常指标。

一句话总结 ​

Kafka 不丢消息三端配合:生产端 acks=all + 重试 + 幂等,Broker 多副本 + min.insync.replicas + 禁 unclean 选举,消费端 处理成功再手动提交 offset + 业务幂等;代价是可能重复消费,靠幂等达到近似精确一次。

基于 VitePress 重建