Kafka 的 ISR、acks 与副本机制如何保证可靠性?
结论先行:每个分区有多个副本,只有 leader 提供读写,follower 异步拉取同步。ISR 是与 leader 保持同步的副本集合,acks 决定生产者要等多少副本确认,min.insync.replicas 给出确认下限。可靠性配置的本质是在"可用性"与"不丢数据"之间做取舍。
一、ISR 与副本同步
- 副本角色:leader 负责读写,follower 从 leader 拉取数据并写入本地日志;
- ISR 定义:与 leader 差距在允许范围内的副本集合(含 leader),落后超时(replica.lag.time.max.ms)会被踢出 ISR;
- 高水位(HW):消费者只能读到 HW 之前的数据,避免读到未同步数据后在 leader 切换时丢失;
- leader epoch:0.11 引入,解决旧版依赖 HW 截断可能造成的数据丢失或不一致问题;
- 同步机制:follower 周期性向 leader 发送 FETCH 请求拉取新数据,写入本地日志后推进 LEO;
- ISR 进出:副本追平进度后可自动回到 ISR,频繁进出意味着该副本不稳定,需排查磁盘或网络。
二、acks 参数对比
| acks | 含义 | 可靠性 | 性能 |
|---|---|---|---|
| 0 | 发出去就不管 | 可能丢,吞吐最高 | 最高 |
| 1 | leader 写入本地即确认 | leader 宕机可能丢 | 中 |
| all(-1) | ISR 全部确认才返回 | 最可靠 | 较低 |
三、可靠性与可用性的配合配置
- acks=all 时若 ISR 只剩 leader,依然只有一份确认,所以还要配 min.insync.replicas=2,副本不足则写入报错;
- unclean.leader.election.enable=false:禁止落后于 HW 的副本参与 leader 选举,防止选出一个丢数据的 leader;
- 生产端 retries + 幂等生产者:网络抖动重试不会产生重复或乱序;
- 组合建议:acks=all + min.insync.replicas=2 + 副本数 3,在多数场景达到较优的不丢保障;
- 写入路径总结:生产者 → leader 本地落盘 → ISR 同步 → 达到 acks 条件后返回,acks=all 响应最慢但最稳;
- 读写可靠性分工:acks 管"写不丢",消费端位移提交管"读不丢",两者常被放在一起考。
四、生产推荐配置
acks=all
min.insync.replicas=2
enable.idempotence=true
常见追问 / 记忆点
- 追问:acks=all 就绝对不丢吗?答:不是,若 ISR 中只有 leader 或 leader 宕机前未同步,仍可能丢,需要 min.insync.replicas 配合。
- 追问:ISR 里的副本落后了会怎样?答:超时被移出 ISR,追平后再重新加入,期间不参与 acks=all 的确认。
- 追问:为什么消费者只能读 HW 之前的数据?答:防止读到只在 leader 上的数据,leader 切换后这些数据可能丢失造成不一致。
- 记忆点:ISR 是健康副本集合,acks 管等谁确认,min.insync 管下限,三个参数一起答才完整。