在学习 Kafka 时,经常会看到一句话:Kafka 可以保证消息不丢失。
但严格来说,这句话并不完整。
Kafka 并不是“无论怎么配置、无论发生什么故障都绝对不会丢消息”,而是通过 副本机制、ISR、ACK 确认机制、min.insync.replicas、生产者重试和幂等性 等多层机制,把消息丢失的风险尽可能降低。
真正应该记住的是:
Kafka 的可靠性来自一整套机制配合,而不是某一个配置项。
这篇文章就从一条消息发送到 Kafka 的完整过程出发,把 acks、Leader/Follower、副本、ISR、HW/LEO 以及生产环境常见配置一次讲清楚。
一、先看结论:Kafka 靠什么降低消息丢失风险?
一条消息要可靠地进入 Kafka,核心会经过下面几层保护:
Producer 将消息发送给分区的 Leader。
Leader 把消息追加到自己的日志。
Follower 从 Leader 拉取数据并复制到自己的日志。
Kafka 维护 ISR,剔除长时间无法跟上 Leader 的副本。
Producer 通过 acks 决定需要等待到什么程度才认为发送成功。
min.insync.replicas 限制 ISR 太少时是否还允许继续写入。
Leader 故障后,Kafka优先从安全的副本集合中重新选举 Leader。
Producer 通过重试和幂等性处理临时网络故障,减少丢失和重复写入问题。

所以 Kafka 的可靠性并不是单点机制,而是从 生产者 → Broker → 副本 → 故障恢复 一层一层保证的。
二、Kafka 为什么需要副本?
Kafka 的数据不是以 Topic 为最小副本单位,而是以 Partition(分区) 为复制单位。
假设有一个 Topic:
order-topic
其中 Partition 0 配置了 3 个副本:
Broker 1:Leader
Broker 2:Follower
Broker 3:Follower
这里的副本数就是:
replication.factor = 3
在正常情况下,一个 Partition 只有一个 Leader,另外的副本作为 Follower。
Producer 写消息时,首先写入 Leader;Follower 再不断从 Leader 拉取消息并复制到自己的日志中。Kafka 官方文档也明确说明,一个分区的复制单位就是 Partition,Follower 会持续复制 Leader 的日志。
为什么不能只保存一份?
如果只有 Leader 一份数据:
Producer
↓
Leader
Leader 所在 Broker 一旦发生磁盘损坏或者机器故障,这部分数据就可能直接不可用甚至丢失。
有副本以后:
┌── Follower 1
Producer → Leader
└── Follower 2
即使 Leader 挂掉,只要有合适的 Follower 保存了已经提交的数据,就可以从剩余副本中恢复。
这就是 Kafka 可靠性的第一层:副本冗余。
三、Leader 和 Follower 分别负责什么?
Leader 是这个 Partition 当前的主要副本。
Producer 的写入会发送给 Leader。
可以简单理解成:
Producer → Leader
Leader 收到消息后追加到自己的日志中,再由 Follower 复制。
2. Follower
Follower 不负责决定消息顺序,它会持续从 Leader 拉取消息,让自己的日志尽量追上 Leader。
Leader
↓
Follower 1
Follower 2
如果 Leader 发生故障,Kafka 会进行 Leader 选举,让满足条件的副本接替 Leader。
但这里马上会出现一个关键问题:
是不是所有 Follower 都能直接成为新的 Leader?
不是。
因为有些 Follower 可能已经落后很多消息。
这就引出了 Kafka 中非常重要的概念:ISR。
四、ISR 到底是什么?
ISR 的全称是:
In-Sync Replicas
即:与 Leader 保持同步的一组副本。
假设一个 Partition 有三个副本:
Leader
Follower 1
Follower 2
正常情况下:
ISR = [Leader, Follower 1, Follower 2]
如果 Follower 2 因为网络、机器负载或其他原因长时间跟不上 Leader,它就可能被移出 ISR:
ISR = [Leader, Follower 1]
Kafka 4.3 的 Broker 配置中,replica.lag.time.max.ms 用于判断 Follower 是否长时间没有追上 Leader;默认值为 30 秒。超过这个条件后,Follower 会被移出 ISR。
这一步非常重要。
因为 Kafka 不能让一个严重落后的副本还被当成“安全副本”。否则 Leader 一挂,如果直接让这个落后的 Follower 上位,刚写进去的数据就可能消失。
因此可以这样记:
副本是“我有数据副本”,ISR 是“我现在仍然跟得上 Leader,可以被认为是同步副本”。
五、ACK 是什么?
Producer 把消息发送给 Kafka 后,需要知道:
这条消息到底算不算发送成功?
这个确认级别由:
acks
控制。
Kafka 当前支持三个主要级别:
acks=0
acks=1
acks=all

六、acks=0:发出去就不管了
配置:
acks=0
Producer 把消息写入网络缓冲区后就认为发送完成,不等待 Broker 的任何确认。
流程类似:
Producer → Kafka
Producer:我已经发出去了,继续干别的
这种方式速度快、等待时间少,但可靠性最低。
例如 Producer 刚把数据发出去,此时:
网络断了
Broker 没收到
Leader 正好发生故障
Producer 都可能不知道。
Kafka 官方 Producer 配置说明中也明确指出,acks=0 时无法保证服务端已经收到消息,而且 Producer 通常无法感知发送失败,因此 retries 也无法正常发挥作用。
适合什么场景?
更适合对少量丢失不敏感、极端追求吞吐或延迟的场景。
对于订单、支付、库存等重要业务消息,一般不应该这样配置。
七、acks=1:Leader 写成功就返回
配置:
acks=1
流程:
Producer
↓
Leader 写入本地日志
↓
返回 ACK
注意:Leader 返回 ACK 时,不要求所有 Follower 已经复制完成。
于是可能发生这种情况:
1. Producer 发送 message-A
2. Leader 写入 message-A
3. Leader 返回 ACK
4. Follower 还没有复制 message-A
5. Leader 突然宕机
此时新的 Leader 如果来自还没有复制到 message-A 的副本,这条消息就可能丢失。
所以:
acks=1 比 acks=0 可靠,但依然存在 Leader 已确认、Follower 尚未完成复制时的数据丢失窗口。
八、acks=all:可靠性最强
配置:
acks=all
或者:
acks=-1
二者含义相同。
acks=all 表示 Leader 要等待 当前 ISR 中的全部副本确认收到这次写入,才会向 Producer 返回成功。
假设:
ISR = [Leader, Follower 1, Follower 2]
那么流程可以理解为:
Producer
↓
Leader
↓
Follower 1
Follower 2
↓
ISR 中副本确认
↓
Producer 收到成功结果
因此即使 Leader 随后发生故障,只要还有至少一个已经同步的安全副本存活,已经成功确认的消息仍然可以用于故障恢复。
Kafka 4.3 Producer 当前的 acks 默认值就是:
all
这是三个 ACK 级别中最强的持久性保证。
九、一个特别容易搞错的地方:acks=all ≠ 所有副本
很多人第一次看到 all,会理解成:
replication.factor 有 3 个副本,就必须等 3 个副本。
这个说法不够准确。
acks=all 等待的是:
当前 ISR 中的全部副本。
例如最初:
replication.factor = 3
ISR = [Leader, Follower 1, Follower 2]
这时 acks=all 会等待这 3 个 ISR 副本。
但如果 Follower 2 已经故障并被移出 ISR:
ISR = [Leader, Follower 1]
此时 acks=all 等待的就是当前 ISR 中这 2 个副本。
那么又有一个问题:
如果只剩 Leader 自己还在 ISR,acks=all 会不会也成功?
如果没有其他限制,确实可能。
这就是为什么还需要 min.insync.replicas。
十、min.insync.replicas 是什么?
min.insync.replicas 可以理解成:
当 Producer 使用 acks=all 时,Kafka 至少要求 ISR 中还存在多少个副本,才允许这次写入成功。
例如生产环境常见配置:
replication.factor = 3
min.insync.replicas = 2
acks = all

情况 1:三个副本都正常
ISR = [Leader, Follower 1, Follower 2]
满足:
ISR 数量 = 3 >= 2
正常写入。
情况 2:一个 Follower 挂了
ISR = [Leader, Follower 1]
满足:
ISR 数量 = 2 >= 2
依然允许写入。
情况 3:只剩 Leader
ISR = [Leader]
此时:
ISR 数量 = 1 < 2
Kafka 会拒绝写入,Producer 会收到类似 NotEnoughReplicas 或 NotEnoughReplicasAfterAppend 的异常。
这看起来好像“Kafka 挂了”,实际上它是在主动做取舍:
宁愿暂时不能写,也不要只保存一份数据然后告诉 Producer 写成功。
这就是典型的:可用性与数据可靠性之间的权衡。
十一、为什么 replication.factor=3 + min.insync.replicas=2 很常见?
组合:
replication.factor = 3
min.insync.replicas = 2
acks = all
可以做到:
正常情况下有 3 份副本。
允许损坏 1 个副本后继续写入。
当只剩 1 个同步副本时拒绝继续确认高可靠写入。
因此它在可靠性和可用性之间比较均衡。
例如创建 Topic 时可以这样配置:
bin/kafka-topics.sh –create –topic order-events –bootstrap-server localhost:9092 –partitions 3 –replication-factor 3 –config min.insync.replicas=2
生产者则使用:
acks=all
enable.idempotence=true
注意,Kafka 4.3 中 Producer 默认已经是 acks=all,并且在没有冲突配置时,enable.idempotence 默认启用。但在学习和生产配置中,把关键可靠性参数明确写出来通常更容易阅读和维护。
十二、ISR 为什么能降低 Leader 故障时的数据丢失风险?
假设当前:
ISR = [Broker 1, Broker 2, Broker 3]
其中:
Broker 1 = Leader
Broker 2 = Follower
Broker 3 = Follower
Producer 使用:
acks=all
一条消息已经被确认成功,意味着它已经到达当前 ISR 所要求的复制条件。
如果此时 Broker 1 突然宕机,Kafka 会进行 Leader 故障恢复,从满足安全条件的副本中选出新的 Leader。
因此新的 Leader 能继续携带已经提交的数据。
Kafka 官方设计文档给出的核心保证是:
已提交的消息,在始终至少存在一个同步副本存活的前提下,不会因为 Leader 故障而丢失。
所以 ISR 的意义不仅是“记录谁同步了”,更重要的是:
它决定了哪些副本可以被认为拥有足够新的数据来参与安全恢复。
十三、HW 和 LEO 又是什么?
在理解副本同步时,经常会看到两个概念:
LEO
HW
可以把 LEO 直观理解为:
某个副本当前日志写到哪里了。
例如:
Leader LEO = 11
Follower 1 LEO = 10
Follower 2 LEO = 8
说明各个副本的复制进度不同。
2. HW:High Watermark
HW 可以直观理解为 Kafka 已经推进到的安全提交/可见边界。

Leader 的日志末尾可能已经有一些新消息,但这些消息还没有完成 ISR 所要求的同步条件。
所以:
Leader LEO
往往可能比:
HW
更靠后。
这也是为什么不能简单认为:
“Leader 本地已经写进日志 = 消息已经完全安全。”
Kafka 会区分“Leader 已经拥有的数据”和“已经达到提交条件的数据”。
十四、Producer 重试为什么也很重要?
即使 Broker 端已经有副本机制,Producer 仍然可能遇到:
网络抖动
Leader 切换
请求超时
临时 Broker 故障
这种情况下,如果 Producer 完全不重试,一次短暂故障就可能让消息发送失败。
Kafka Producer 提供:
retries
当前 Kafka 4.3 Producer 的默认 retries 已经是一个非常大的值,官方更建议通过 delivery.timeout.ms 控制一次消息发送整体允许的重试时间。
但重试会带来另一个问题:
Producer → Broker
Broker 已经写成功
ACK 返回过程中网络断开
Producer 没收到 ACK
Producer 再次发送
这时 Broker 可能收到两次相同消息。
因此 Kafka 又提供了:
enable.idempotence
十五、enable.idempotence:防止 Producer 重试导致重复写入
配置:
enable.idempotence=true
启用幂等生产者后,Kafka 会避免因为 Producer 的重试导致同一条记录被重复写入日志。
Kafka 4.3 中,在没有冲突配置的情况下,幂等性默认启用。
启用幂等性要求:
acks = all
retries > 0
max.in.flight.requests.per.connection <= 5
当前默认的 max.in.flight.requests.per.connection 为 5。
所以对于重要消息,推荐思路通常是:
acks=all
enable.idempotence=true
再配合 Broker / Topic 端:
replication.factor = 3
min.insync.replicas = 2
形成比较完整的可靠性链路。
十六、Kafka 在什么情况下仍然可能丢消息?
这部分非常重要。
不要因为使用了 Kafka 就认为消息绝对不会丢。
情况 1:使用 acks=0
acks=0
Producer 不等服务器确认,本身就没有可靠发送保证。
情况 2:使用 acks=1,Leader 刚确认就故障
acks=1
Follower 可能还没来得及复制。
情况 3:副本因子只有 1
replication.factor = 1
只有一份数据,Broker 或磁盘发生不可恢复故障时,就没有其他副本可用。
Kafka 4.3 中 default.replication.factor 的默认值仍然是 1,因此生产环境不能只看到 Producer 默认 acks=all 就认为可靠性配置已经完整。
情况 4:acks=all,但 min.insync.replicas 太低
例如:
replication.factor = 3
min.insync.replicas = 1
只剩一个 ISR 副本时仍可能接受写入,随后这个唯一副本再发生故障,风险就会明显增大。
情况 5:开启非同步副本的 Leader 选举
Kafka 的配置:
unclean.leader.election.enable
允许不在 ISR 中的副本在必要时成为 Leader。
这样做可以提高某些极端故障下的可用性,但可能带来数据丢失。
Kafka 4.3 中这个配置默认是:
false
也就是说默认更偏向数据安全。
情况 6:所有同步副本的数据都不可恢复
任何副本机制都不是无限可靠。
如果一个 Partition 的所有有效副本都同时发生不可恢复的数据损坏,就已经超出了“还有同步副本可恢复”的前提。
十七、推荐的可靠性配置组合
对于订单、支付、库存、交易事件等比较重要的消息,可以把下面这套配置作为理解可靠性的基础模板。
Topic:
replication.factor = 3
min.insync.replicas = 2
Producer:
acks=all
enable.idempotence=true
同时保持:
unclean.leader.election.enable = false
整体逻辑就是:
Producer
↓
acks=all
↓
Leader
↓
ISR Followers
↓
至少保持足够数量的同步副本
↓
发送成功
这样,即使某台 Broker 出现故障,也有其他同步副本可以继续承担数据恢复工作。
十八、acks、ISR、min.insync.replicas 三者到底是什么关系?
这是整篇文章最核心的部分。
acks
解决:
Producer 要等到什么程度才认为消息发送成功?
ISR
解决:
当前哪些副本仍然被认为和 Leader 保持同步?
min.insync.replicas
解决:
当使用 acks=all 时,ISR 至少还要剩多少个副本,Kafka 才允许继续成功写入?
三者配合:
Producer
│
│ acks=all
▼
Leader
│
├── Follower 1 ┐
└── Follower 2 ├── ISR
│
min.insync.replicas
│
▼
判断是否允许写入
一句话记忆:
acks 决定“等谁”,ISR 决定“谁算同步副本”,min.insync.replicas 决定“同步副本少到什么程度就不写了”。
十九、常见误区
误区 1:acks=all 就绝对不丢
错误。
还要看:
replication.factor
min.insync.replicas
ISR 状态
Leader 选举策略
副本是否还能恢复
误区 2:acks=all 就是等 replication.factor 个副本
不准确。
它等待的是:
当前 ISR 中的全部副本
误区 3:min.insync.replicas=2 就是只等两个 ACK
不准确。
它首先是一个最小 ISR 数量门槛。
当前 Kafka 文档还特别说明:当 acks=all 时,是当前 ISR 中所有副本都要确认;min.insync.replicas 决定 ISR 少于多少时直接失败。
误区 4:Follower 越多越好
副本越多,数据冗余能力通常越强,但同时也会增加:
存储空间
网络复制流量
Broker I/O
故障恢复和运维成本
所以副本数不是无限增加,而是根据可靠性要求和集群规模选择。
误区 5:Producer 收到成功就等于业务绝对安全
Kafka 解决的是消息在消息系统中的可靠存储和传输问题。
业务侧仍然需要考虑:
消费成功后何时提交 Offset
消费失败如何重试
数据库事务是否成功
消费者幂等
重复消息
这些属于消费者可靠性和端到端一致性问题,不能只靠 Producer 的 ACK 解决。
二十、最后总结
Kafka 消息可靠性的核心,不是“有一个神奇配置让消息永远不会丢”,而是一套机制共同作用:
副本机制
+
Leader / Follower
+
ISR
+
acks=all
+
min.insync.replicas
+
Producer retries
+
enable.idempotence
其中最重要的逻辑可以记成:
Producer 把消息写给 Leader
↓
Follower 从 Leader 复制
↓
Kafka 维护 ISR
↓
acks 决定 Producer 等待的确认级别
↓
min.insync.replicas 防止同步副本太少仍继续确认写入
↓
Leader 故障后从安全副本中恢复
如果只记一句话:
Kafka 所谓“消息不丢”,本质是通过多副本保存数据,用 ISR 筛选安全副本,再通过 ACK 和最小 ISR 门槛决定什么时候才能向 Producer 宣布写入成功。
这才是 Kafka 可靠性机制真正的核心。
参考资料
Apache Kafka 4.3 Design:Replication / ISR / durability
Apache Kafka 4.3 Producer Configs:acks、retries、enable.idempotence
Apache Kafka 4.3 Topic Configs:min.insync.replicas
Apache Kafka 4.3 Broker Configs:replica.lag.time.max.ms、unclean.leader.election.enable
版本说明:本文按 Apache Kafka 4.3 官方文档整理。Kafka 4.0+ 还引入了 Eligible Leader Replicas(ELR)机制;启用 ELR 时,min.insync.replicas 的部分语义会发生扩展。本文聚焦最常用的 ISR + ACK + 副本可靠性主线,便于理解基础机制。







