Kafka ISR、HW 和 LEO 分别是什么?
面试怎么回答
LEO 是每个副本下一条消息的写入位置,表示各自复制进度;ISR 是与 Leader 保持同步的副本集合,会随 Follower 延迟变化;HW 是已确认日志边界,经典非事务读取中 Offset 小于 HW 才可见。Leader 根据 ISR 进度推进 HW。生产上还要结合 acks=all 和 min.insync.replicas,ISR 不足时拒绝写入,以可靠性换取部分可用性。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
很多人会背三个定义:
“ISR 是同步副本集合,HW 是高水位,LEO 是日志末端位移。”
定义背完,面试官通常会继续追问:三者到底怎么一起保证副本一致性?
真正要理解的是:
LEO 描述每个副本写到哪里,ISR 描述哪些副本跟得上,HW 描述哪些消息已经达到可确认进度。
第一步:LEO 是每个副本自己的进度
LEO 是 Log End Offset,可以理解为该副本下一条消息将要写入的位置。
同一个 Partition 的 Leader 和 Follower 都有自己的 LEO。
例如:
Leader LEO = 15
Follower A LEO = 15
Follower B LEO = 12
说明 Leader 和 A 已经写到相同位置,B 还落后三个 Offset 位置。
因此 LEO 不是全局唯一值,而是观察各副本复制进度的基础。
第二步:ISR 是当前保持同步的副本集合
ISR 是 In-Sync Replicas,包含 Leader 和当前满足同步条件的 Follower。
Follower 会持续从 Leader 拉取数据。如果它长时间没有拉取,或者长时间没有追上 Leader 的 LEO,就可能被移出 ISR;恢复追赶后,可以重新加入。
需要注意:
- AR 是所有分配给该 Partition 的副本
- ISR 是其中当前保持同步的一部分
- ISR 不是固定不变的,会随着副本状态收缩和扩张
副本在 AR 中,不代表它此刻一定具备同样的数据进度。
第三步:HW 是已确认进度的边界
HW 是 High Watermark。
在经典非事务语义下,可以把它理解为第一条尚未提交消息的位置:Offset 小于 HW 的记录,已经达到副本确认要求,可以对 Consumer 可见。
假设:
ISR = {Leader, Follower A}
Leader LEO = 15
Follower A LEO = 15
Follower B LEO = 12,已不在 ISR
HW = 15
那么 Offset 0—14 已经提交。Follower B 虽然落后,但因为已经不在 ISR,不阻塞当前 HW 推进。
事务消费还会受到 LSO 等边界影响,但理解副本复制时,先把 HW 看成“已确认日志的上界”即可。

第四步:它们如何影响写入可靠性
Producer 设置 acks=all 时,成功确认依赖当前 ISR,而不是只看副本总数。
min.insync.replicas 则规定:使用 acks=all 写入时,ISR 至少要有多少个副本,写入才能成功。
例如:
replication.factor = 3
min.insync.replicas = 2
acks = all
当 ISR 有 2 个副本时,写入还能成功;如果 ISR 缩到 1,Broker 会拒绝写入。
这不是 Kafka “坏了”,而是在可用性和数据可靠性之间选择了保护数据:宁可暂时写不进去,也不在副本不足时继续确认高风险写入。
一个典型场景
比如一个三副本 Topic 出现磁盘抖动,一台 Follower 持续落后并被移出 ISR。
此时 AR 仍然是 3,但 ISR 只剩 Leader 和另一台 Follower。业务写入可能继续成功,HW 仍可随两个同步副本推进。
如果第二台 Follower 也掉出 ISR,ISR 只剩 Leader。配置了 min.insync.replicas=2 且 Producer 使用 acks=all 时,新写入会失败。
排查时不能只看 Broker 是否存活,还要看 ISR 收缩、Follower Lag、Under-Replicated Partition 和写入错误。
副本数描述设计冗余,ISR 才描述当前真正可用的同步冗余。