介绍一下 Kafka 的 ISR 机制?

#中间件#面试八股

介绍一下 Kafka 的 ISR 机制?

结论:ISR(In-Sync Replicas)是与 Leader 保持同步的副本集合,包含 Leader 本身。判断标准是 Follower 的拉取进度落后 Leader 不超过 replica.lag.time.max.ms(默认 30 秒)。ISR 有两个作用:决定 acks=all 要等哪些副本,决定 Leader 挂掉后谁能接任。ISR 越短,可靠性越低。

一、ISR 的动态维护

        Leader(LEO=1200, HW=1100)          ISR = [L, F1, F2]
              │  F1 拉取到 1150,F2 只到 800
              ▼
   ┌─────────────────────────────────────────────┐
   │ F2 落后 400 条,且超过 30s 没追上            │
   │  → Controller 把 F2 踢出 ISR                 │
   │  → ISR = [L, F1],F2 进入 OSR(普通副本)     │
   └─────────────────────────────────────────────┘
              │  F2 恢复,持续追到 LEO 附近
              ▼
   F2 重新加入 ISR,HW 恢复推进
参数默认值作用
replica.lag.time.max.ms30000Follower 超过该时长未追上 Leader 则移出 ISR
replica.fetch.max.bytes1MB单次拉取上限,过小会导致大消息同步慢
num.replica.fetchers1Follower 拉取线程数,跨机房/高延迟时可调大
min.insync.replicas1写入时要求的最小 ISR 数量,低于此值 acks=all 抛异常
acksall生产端等待 ISR 全部确认

历史上还有过按消息条数判断的 replica.lag.max.messages,因为大流量下误判严重已被移除,现在只看"时间"。

二、LEO 与 HW 的推进

概念含义谁维护
LEO(Log End Offset)副本下一条待写入消息的位移每个副本各自维护
HW(High Watermark)ISR 中最小的 LEO,消费者可见的上界Leader 维护并随 Fetch 响应下发
LSO(Last Stable Offset)未完成事务之前的位移,read_committed 消费者可见的上界Leader 维护

Follower 发出 FetchRequest(fetchOffset=LEO),Leader 返回数据后 Follower 追加写、推进自己的 LEO,并在下一次 Fetch 中上报;Leader 收到后更新 HW = min(ISR 各副本 LEO),再把 HW 带回响应。HW 的推进至少要一次额外的 Fetch 往返,这就是"副本都写完了但消费者暂时读不到"的原因。

三、ISR 与写入可用性

# Broker
replica.lag.time.max.ms=30000
min.insync.replicas=2
unclean.leader.election.enable=false

# 生产端
acks=all

组合效果:

  • ISR = 3,写入等 3 个副本确认,最稳最慢;
  • ISR 缩到 2,仍满足 min.insync.replicas=2,写入继续但容错降为 0;
  • ISR 缩到 1,低于下限,生产端收到 NotEnoughReplicasException,这是保护而不是故障;
  • 若 min.insync.replicas=1,ISR 只剩 Leader 时 acks=all 退化成 acks=1,看似成功实则单副本。

四、观察与排查

# ISR 列就是当前同步副本集合,副本前的数字是 Leader
kafka-topics.sh --bootstrap-server 10.0.0.31:9092 --describe --topic order-events

# 检查副本之间是否有数据落后
kafka-replica-verification.sh --broker-list 10.0.0.31:9092 \
  --topic-white-list 'order-events'

如果 ISR 频繁收缩,按顺序排查:Follower 所在磁盘 IO 是否打满 → 网络是否抖动 → num.replica.fetchers 是否太小 → 是否单条消息超过 replica.fetch.max.bytes 导致同步卡住。

五、常见追问

  • ISR 包含 Leader 吗? 包含。所以"ISR=1"意味着只剩 Leader,而不是"没有副本"。
  • Follower 落后一点就被踢,会不会太敏感? 判据是"30 秒内是否追上过",短暂抖动不会触发;一旦持续落后,继续留在 ISR 反而会拖慢 HW 推进并增加丢数据风险。
  • ISR 收缩会丢消息吗? 不会直接丢,但缩小了 acks=all 的等待范围,故障时抗风险能力下降。
  • KRaft 下 ISR 由谁管? 由 Controller 统一管理并写入元数据日志,不再依赖 ZooKeeper 节点,变更传播更快。

小结

  • ISR = 与 Leader 同步的副本集合(含 Leader),按时间判据动态进出。
  • acks=all 等的是 ISR,min.insync.replicas 是 ISR 的下限保护。
  • HW = ISR 最小 LEO,决定消费者能读到哪;HW 推进依赖额外的 Fetch 往返。
  • ISR 频繁抖动是磁盘、网络或拉取线程不足的信号,必须查根因而不是调大超时。
笔记加载中…