Kafka 副本与消息可靠性(ISR + 消息不丢 + 100% 边界)

mq 📚 learning kafka-reliability · kafka · reliability · isr · high-watermark · replication · acks · at-least-once

TL;DR(30 秒扫完)

  • 副本三层:AR(静态所有副本)→ ISR(跟上 Leader 的动态子集)→ OBR(落后被踢的副本)
  • HW(High Watermark) = min(所有 ISR 副本 LEO),消费者只能读 HW 之前的消息
  • ISR 动态规则:Follower 超过 replica.lag.time.max.ms(默认 10s)未追上 → 踢出 ISR
  • 消息不丢三段配置:
  • Producer: acks=all + enable.idempotence=true
  • Broker: replication.factor=3 + min.insync.replicas=2 + unclean.leader.election.enable=false
  • Consumer: enable.auto.commit=false + 业务后手动 commitSync + 业务幂等
  • 无法 100% 保证:CAP 权衡、网络异常、进程崩溃、副本全挂、事务超时——工程上没有 100%

关键结论

结论 AKafka 副本一致性靠 ISR + HW 机制,Leader 挂只从 ISR 选新 Leader
结论 B消息可靠性靠"三段链路 + 关键参数"组合,光说"确认"、"落盘"不足以证明工程实践能力
结论 CKafka 只能保证 At-Least-Once,不能保证 Exactly-Once(除非开 Kafka 事务 + 外部存储配合)
结论 D工程上没有 100% 可靠,能做的是把丢失概率降到足够低 + 兜底补偿

完整讲解(费曼四步)

STEP 1 · 概念

ISR(In-Sync Replicas) 是分区中跟上 Leader 进度的副本子集;消息可靠性是指消息从 Producer 到 Consumer 全链路不丢失;100% 边界是 Kafka 的可靠性天花板。

STEP 2 · 大白话

银行多副本比喻:
  • Leader = 总行账本
  • ISR = 各个分行账本,实时跟总行同步
  • HW = "所有分行都同步到的最低一条记录"——客户只能查到 HW 之前的记录,因为之后的可能只有一部分分行有
  • unclean.leader.election = 是否允许一个明显落后的分行当总行(会丢数据)

STEP 3 · 底层

副本三层概念

概念全称说明
ARAssigned Replicas分区的所有副本,静态(配置确定)
ISRIn-Sync ReplicasAR 中跟上 Leader 的副本,动态
OBROut-of-Browser ReplicasAR - ISR,落后被踢的副本(2.4+ 术语)

ISR 动态调整规则

  • Follower 拉取消息超过 replica.lag.time.max.ms(默认 10s)没追上 Leader 的 LEO → 踢出 ISR
  • 追上 Leader 后重新加入 ISR
  • 时间维度,不是 offset 落后多少条

HW 与 LEO

HW  = min(所有 ISR 副本的 LEO)
消费者只能读 HW 之前的消息
  • 如果 ISR 只有 Leader 自己,HW = Leader 的 LEO
  • LEO = 副本最后一条消息的下一个 offset

Leader 选举与故障转移

  • Leader 挂掉 → Controller 从 ISR 中选新 Leader
  • unclean.leader.election.enable=true:可从 OBR 选(会丢数据,生产不打开)
  • min.insync.replicas:Producer acks=all 时至少需要多少 ISR 副本确认

消息不丢三段链路配置

Producer 端:
参数推荐值说明
acksall等所有 ISR 副本确认
retriesMAX_VALUE无限重试
enable.idempotencetrue开启幂等,崩溃不重复
max.in.flight.requests.per.connection5幂等允许的最大值
Broker 端:
参数推荐值说明
replication.factor33 副本
min.insync.replicas2至少 2 副本确认
unclean.leader.election.enablefalse不允许非 ISR 当选 Leader
Consumer 端:
参数推荐值说明
enable.auto.commitfalse关闭自动提交
提交方式业务后 commitSync手动提交
业务幂等必做DB 唯一索引 / Redis / 去重表

为什么无法 100% 保证消息不丢

本质:分布式系统 + 网络不可靠 + 硬件故障 + 进程崩溃,CAP 权衡 三段链路丢失场景:
环节丢失场景
Producer应用崩溃(消息未发)/ 网络分区 / acks=0 时 Leader 挂
BrokerISR 收缩到 1 后 Leader 挂 / unclean.leader.election=true 数据回退 / 硬件故障
Consumeroffset 提交但业务未完成 / 处理完成后 commit 前进程崩溃 / 反序列化失败
系统级ZooKeeper/KRaft Controller 故障 / 事务超时 abort
CAP 权衡:
  • Kafka 选择 AP(网络分区时可用优先)
  • unclean.leader.election=true → 丢数据换可用
  • unclean.leader.election=false → 不可用但不丢数据

At-Least-Once vs Exactly-Once

  • At-Least-Once:Kafka 默认保证,可能重复消费,需要业务幂等
  • Exactly-Once:需要 Kafka 事务 + isolation.level=read_committed,只能保证 Kafka 内部 exactly-once,跨系统仍需外部存储配合

STEP 4 · 简化

一句话总结:ISR 是副本一致性的核心;消息不丢靠"三段链路 + 关键参数"组合;Kafka 只能 At-Least-Once,100% 保证不存在。 记忆口诀:
  • 副本:AR ⊃ ISR ⊃ {Leader},HW = min(所有 ISR LEO)
  • 生产推荐:acks=all + replication=3 + min.insync=2 + unclean=false + 手动 commit
  • 100% 边界:CAP 权衡,只能做到"概率足够低 + 兜底补偿"

常见误区

ISR 是"所有副本"
ISR 是跟上 Leader 的动态子集,AR 才是所有副本
ISR 落后多少条就踢出
是时间维度(replica.lag.time.max.ms)
unclean.leader.election=true 是安全的
会丢数据,生产必须关闭
Kafka 能保证 Exactly-Once
只能保证 At-Least-Once,Exactly-Once 需要事务且只限 Kafka 内部
acks=1 就够了
Leader 挂时消息可能丢失;生产用 acks=all + min.insync=2
工程上可以做到 100% 保证不丢
不可能,只能做到"概率足够低 + 兜底补偿"

延伸追问

min.insync.replicas=2 但 ISR 只剩 1 个,会怎样?
Producer 请求阻塞到 request.timeout.ms,业务侧报错;需扩容副本或临时降级。
为什么 Kafka 选择 ISR 而不是 Raft 的多数派?
ISR 用"追上"作为一致判断,简单高效;Raft 需要 term、votedfor、日志匹配,Kafka 复杂度更高收益不大。
HW 会一直等于 LEO 吗?
正常时接近,Follower 挂掉时 HW 停滞,直到新副本追上。
Kafka 事务能保证跨系统事务吗?
不能。只能保证 Kafka 内部 exactly-once,外部存储需要业务侧配合(本地消息表、SAGA)。
如何设计"几乎不丢消息"的系统?
Producer acks=all + enable.idempotence=true;Broker replication.factor=3 + min.insync=2 + unclean=false;Consumer 手动 commit + 业务幂等;外部存储用事务或最终一致性;再加对账机制。
unclean.leader.election.enable=true 会带来什么后果?
可能选到落后的副本作为 Leader,已提交的消息可能被后续写入覆盖,数据丢失;生产上一般关闭。

速查表

副本: AR ⊃ ISR ⊃ {Leader};OBR = AR - ISR
HW:   min(所有 ISR 副本的 LEO),消费者只能读 HW 之前
踢出: replica.lag.time.max.ms(默认 10s)未追上 → 踢出 ISR
生产配置: acks=all + idempotence=true + replication=3 + min.insync=2 + unclean=false + 手动 commit + 业务幂等
100% 边界: CAP 权衡,无法 100%;只能 At-Least-Once(+ 业务幂等 = Exactly-Once 效果)
事务局限: Kafka 事务只保证 Kafka 内部 exactly-once,跨系统需外部配合

Anki 候选卡片

Q: Kafka 副本三层概念?
A: AR(所有副本)⊃ ISR(跟上 Leader)⊃ {Leader};OBR = AR - ISR
Q: HW(High Watermark)怎么算?
A: HW = min(所有 ISR 副本的 LEO),消费者只能读 HW 之前
Q: ISR 踢出条件?
A: Follower 超过 replica.lag.time.max.ms(默认 10s)未追上 Leader LEO
Q: 生产推荐的副本配置组合?
A: replication.factor=3 + min.insync.replicas=2 + unclean.leader.election.enable=false
Q: Kafka 能保证 Exactly-Once 吗?
A: 不能,只能 At-Least-Once;Exactly-Once 需要事务且只限 Kafka 内部
Q: unclean.leader.election.enable=true 的后果?
A: 非 ISR 副本当选 Leader,可能覆盖已提交消息,数据丢失
Q: 为什么 Kafka 无法 100% 保证消息不丢?
A: CAP 权衡、网络异常、进程崩溃、副本全挂、事务超时——工程上没有 100%
Q: 消息不丢的三段链路配置?
A: Producer acks=all + idempotence;Broker replication=3 + min.insync=2;Consumer 手动 commit + 业务幂等

关联题目

  • ⚠️ 《介绍一下 Kafka 的 ISR 机制?》— Round 2 Q6, 未作答
  • ⚠️ 《Kafka 如何保证消息不丢失?》— Round 2 Q7, ⭐⭐⭐(框架对,漏具体参数)
  • ✅ 《为什么 Kafka 没办法 100% 保证消息不丢失?》— Round 2 Q9, ⭐⭐⭐⭐(本轮最佳)

关联知识

ISR 是副本一致性核心;消息不丢靠三段链路+参数;Kafka 只能 At-Least-Once
银行多副本:Leader 是总行账本,ISR 是分行账本,HW 是所有分行都同步到的最低记录
✦ 记 忆 口 诀 ✦
acks=all + replication=3 + min.insync=2 + 手动 commit + 业务幂等
关键可视化
ISR + HW + LEO 关系
flowchart TD
  A[AR 所有副本] --> B[ISR 跟上 Leader 的动态子集]
  A --> C[OBR 落后被踢的副本]
  B --> D[Leader]
  B --> E[Follower 1]
  B --> F[Follower 2]
  D --> G[LEO = 副本最后一条消息的下一个 offset]
  E --> H[LEO]
  F --> I[LEO]
  G --> J[HW = min 所有 ISR 副本的 LEO]
  H --> J
  I --> J
  J --> K[消费者只能读 HW 之前的消息]
消息不丢三段链路配置
flowchart LR
  A[Producer 端] --> A1[acks=all]
  A --> A2[enable.idempotence=true]
  A --> A3[max.in.flight=5]
  B[Broker 端] --> B1[replication.factor=3]
  B --> B2[min.insync.replicas=2]
  B --> B3[unclean.leader.election.enable=false]
  C[Consumer 端] --> C1[enable.auto.commit=false]
  C --> C2[业务后 commitSync]
  C --> C3[业务幂等 必做]
为什么无法 100 保证消息不丢
flowchart TD
  A[无法 100 保证] --> B[CAP 权衡]
  A --> C[网络异常]
  A --> D[进程崩溃]
  A --> E[副本全挂]
  A --> F[事务超时 abort]
  B --> B1[unclean=true 丢数据换可用]
  B --> B2[unclean=false 不可用但不丢]
  C --> C1[应用崩溃消息未发]
  D --> D1[处理完 commit 前崩溃]
  E --> E1[ISR 收缩到 1 后 Leader 挂]
知识关系

⬆️ 前置(Prerequisite)

kafka-partition-performance

🔄 延伸(Extends)

暂无

⚡ 对比(Contrast)

Kafka 事务消息— 事务消息只能保证 Kafka 内部 exactly-once,跨系统仍需业务配合
🎯 概念 📏 规则 ⚠️ 误区 🔍 追问 ✨ 口诀 共 0 张卡,点击翻面