Appearance
ISR、unclean leader election 和可用性边界
Kafka 的高可用不是“有多个副本”这么简单。
真正决定你在故障时是“少量不可用”还是“直接丢数据”的,往往就藏在 ISR 和 unclean leader election 这两个点里。
如果这条线没理解清楚,很多配置看起来都像参数,实际上是在改系统容错边界。
先说结论
- ISR 是“已跟上 leader 的副本集合”,它决定了副本复制的安全边界
- unclean leader election 允许非 ISR 副本在故障时抢主,提升可用性,但可能带来数据丢失
- 这不是“开不开某个参数”的小问题,而是在数据安全和可用性之间选倾向
- 线上看到 ISR 频繁收缩、扩张,要优先排查复制延迟、磁盘、网络和 broker 压力
ISR 到底是什么
Kafka 每个 partition 会有多个副本:
- 一个 leader
- 多个 follower
但不是所有 follower 都随时足够“新”。
只有跟进程度足够的副本,才会进入 ISR,也就是 in-sync replicas。
可以简单理解成:
- 所有副本不等于都可靠可接班
- ISR 里的副本才算当前安全候选人
为什么 ISR 这么重要
因为它影响两个关键动作:
1. 生产确认
当你设置 acks=all 时,生产成功通常意味着消息至少被 leader 和 ISR 中要求的副本确认。
2. leader 故障切换
正常情况下,leader 挂掉后,新 leader 应该从 ISR 中选。
这样才能尽量保证新 leader 不会比旧 leader 落后太多。
所以 ISR 本质上是在定义“我信哪些副本现在足够新,可以参与安全接班”。
ISR 为什么会变小
如果 follower 跟不上 leader,它就可能被踢出 ISR。
常见原因有:
- 磁盘写慢
- 网络抖动
- broker CPU 高
- 副本拉取跟不上
- 大量 page cache 抖动
这时会出现一个很重要的现象:
副本还活着,但已经不算“同步副本”了。
unclean leader election 到底在干什么
正常情况下,leader 宕机后,只从 ISR 里选新 leader。
这样更安全,因为这些副本理论上足够新。
但如果 ISR 里已经没有可用副本了,怎么办?
这时系统有两种选择:
1. 不选
分区暂时不可用,但尽量不冒数据不一致风险。
2. 从非 ISR 副本里硬选一个
这就是 unclean leader election。
它的代价是:
新 leader 可能缺少旧 leader 上已经接收但尚未同步出去的消息。
也就是说,可能丢数据。
所以它到底是在换什么
一句话:
- 关掉 unclean: 更偏数据安全,分区可能短时不可用
- 打开 unclean: 更偏可用性,故障时可能恢复更快,但可能丢消息
这就是可用性边界。
一个典型故障场景
假设一个分区有 3 个副本:
- leader 在 broker A
- follower 在 broker B、C
此时:
- B 因磁盘慢被踢出 ISR
- C 因网络问题也跟不上
- leader A 突然宕机
这时如果:
unclean.leader.election.enable=false分区可能暂时不可用unclean.leader.election.enable=trueB 或 C 可能被提成 leader,但旧 leader 上尚未同步出去的数据可能丢失
这不是理论问题,而是线上真实故障里会出现的取舍。
为什么很多团队生产上默认不开 unclean
因为大多数核心业务链路更怕“静默丢消息”,而不是“短时不可用后恢复”。
特别是:
- 订单
- 支付
- 库存
- 账务
这类链路通常宁可让分区短暂不可用,也不希望因为非 ISR 副本接班而丢掉已写入消息。
但关闭 unclean 也不代表万事大吉
如果 ISR 长期很脆弱,即使关闭 unclean,也会频繁看到:
- 分区不可用
- leader election 失败
- producer 超时
所以真正问题不只是“开不开 unclean”,而是“为什么 ISR 会收缩到不健康”。
工程上该重点看什么
1. ISR 收缩频率
如果某些 topic / partition 的 ISR 经常波动,说明副本复制链路不稳。
2. follower lag
看副本落后量和同步延迟,判断是不是某台 broker 长期跟不上。
3. broker 资源瓶颈
磁盘 IO、网络带宽、page cache、CPU 和 GC 都会影响副本追赶能力。
4. topic 配置
还要结合:
replication.factormin.insync.replicas- producer
acks
这些一起才决定真正的可靠性边界。
最容易被忽略的一点
很多团队把 acks=all 当成“绝对不丢消息”的保证。
实际上它只是在当前 ISR 语义下尽量保证更强确认。
如果 ISR 本身已经收缩得很危险,或者后续 leader 选举策略激进,整体可靠性边界仍然会变。
一个简单判断模型
如果你的业务更怕丢消息,通常倾向于:
acks=all- 合理的
min.insync.replicas - 关闭
unclean leader election - 重点治理 ISR 稳定性
如果你的业务极度强调在线可用,且能容忍小范围消息损失,策略才可能往另一边偏。
总结
ISR 和 unclean leader election 的核心,不是记住名词,而是看明白:
- 哪些副本真正能安全接班
- 系统在故障时宁可停一下,还是宁可冒丢数据风险继续服务
这条边界一旦想清楚,Kafka 的高可用配置就不再只是参数,而是明确的业务决策。