Kafka 副本机制
概述
副本机制是 Kafka 高可用与可靠性的基石。Leader 负责读写,Follower 同步数据;ISR 保证同步集合;Ack 决定写多"稳";Min ISR 平衡可用性与一致性。本文讲透副本同步与 Ack 的全套机制。
一、副本基本概念
1.1 副本与分区
Topic → Partition → Replica
每个分区有多个副本
一个 Leader + N 个 Follower
副本分布在不同 Broker| 角色 | 职责 |
|---|---|
| Leader | 处理读写请求 |
| Follower | 拉取同步,故障时替补 |
| AR | 分区的全部副本集合 |
| ISR | 与 Leader 同步的副本集合 |
副本因子:
副本数 = 冗余度
副本数 ≤ Broker 数
生产常用:2 或 31.2 为什么需要副本
价值:
高可用:Leader 挂了自动切换
数据可靠:多份存储防丢失
容灾:跨机架/机房分布
代价:
存储翻倍
同步开销
写放大二、Leader 与 Follower 同步
2.1 同步流程
写入流程(ack=all):
Producer → Leader 落盘
→ Follower 拉取(fetch)并写入
→ Follower 向 Leader 确认
→ Leader 更新 HW
→ Producer 收到成功2.2 拉取式同步
为什么 Follower 用拉取:
Leader 不知道 Follower 能力
拉取可自控节奏(背压天然)
批量拉取效率高
机制:
Follower 定期拉取 Leader 数据
从自己的 LEO 位置开始拉
拉取后写本地并更新 LEO2.3 同步中的关键偏移量
| 概念 | 含义 |
|---|---|
| LEO | 本地日志末端偏移 |
| HW | 高水位(可被消费者见) |
| Remote LEO | Leader 视角的 Follower LEO |
HW 推进:
HW = ISR 中最小的 LEO
只有 Follower 追到 HW,Leader 才推进 HW
消费者只能读到 HW 之前的消息三、ISR 伸缩机制
3.1 ISR 加入与退出
加入条件(Follower 跟得上):
持续向 Leader 拉取
延迟小于阈值(replica.lag.time.max.ms)
落后于 HW 的差距小于阈值
退出条件(跟不上的 Follower):
拉取超时/落后过多
被踢出 ISR → 不能再被选为 Leader
恢复后再重新加入3.2 ISR 变化示例
ISR = [0, 1, 2](Leader=0,1/2 同步中)
Follower 2 网络故障
→ 延迟超阈值 → ISR = [0, 1]
Follower 2 恢复 → 追平 HW
→ ISR = [0, 1, 2]3.3 相关配置
| 配置 | 说明 |
|---|---|
| replica.lag.time.max.ms | 副本落后判定阈值 |
| num.replica.fetchers | 拉取线程数 |
四、Leader 选举
4.1 选举时机
触发场景:
Leader 所在 Broker 宕机
分区副本数变化(重分配)
Broker 优雅下线
选举原则:
优先从 ISR 中选择
多数派提交的偏移量保障4.2 选举算法
选举步骤:
1. Controller 感知 Leader 故障
2. 从分区 ISR 列表选候选
3. 优先副本序号最小且存活的
4. 发送 LeaderAndIsr 请求通知
5. 新 Leader 开始接收读写4.3 优先副本(Preferred Replica)
概念:
分区创建时第一个副本
理想 Leader(分布均衡)
均衡机制:
Leader 均衡任务定期执行
把 Leader 换回优先副本
避免 Leader 集中在少数 Broker五、Unclean Leader 选举
5.1 什么是 Unclean 选举
场景:
ISR 内副本全部不可用
只有落后副本还活着
两种选择:
等 ISR 恢复(牺牲可用性,保数据)
选落后副本(牺牲一致性,保可用性)5.2 配置与影响
| 配置 | 值 | 影响 |
|---|---|---|
| unclean.leader.election.enable | false | 不选非 ISR 副本,可能长时间不可用 |
| unclean.leader.election.enable | true | 可用性优先,可能丢消息 |
风险示例:
ISR=[0,1],2 是落后副本
0/1 宕机 → 启用 unclean → 选 2
2 上没有最新消息 → 数据丢失
(丢失的是 2 未同步的部分)5.3 生产建议
建议:
核心消息 → 关闭 unclean(宁可等待)
非核心/日志 → 可开启(保可用)
配合 Min ISR + Ack 从源头降低风险六、Min ISR 与 Ack 原理
6.1 Ack 语义
| Ack 值 | 含义 | 可靠性 |
|---|---|---|
| 0 | 发完即走 | 最弱,可能丢 |
| 1 | Leader 落盘即回 | 中等 |
| all | ISR 全部落盘 | 最强 |
生产参数:
acks=all + min.insync.replicas=2
只有 ISR ≥ 2 时写才成功
否则抛异常(宁可失败不降级)6.2 Min ISR 的作用
Min ISR(min.insync.replicas):
写入的最低同步副本数要求
ISR < Min → 拒绝写入
价值:
防止 Leader 单点独裁
保证写入至少有 N 份
配合 ack=all 实现强可靠示例:
min.insync.replicas=2,ISR=[0,1]
Broker 1 宕机 → ISR=[0] < 2
→ 写入失败(保护数据)
Broker 1 恢复 → ISR=[0,1] → 恢复写入6.3 可靠性与可用性权衡
权衡三角:
可靠性(多副本确认)
可用性(随时可写)
性能(写入延迟)
生产默认:
acks=all,min.insync.replicas=2
均衡可靠与可用七、副本故障处理
7.1 Follower 故障
处理流程:
踢出 ISR
Leader 继续服务(HW 不推进或只推 ISR 内)
故障恢复 → 从 Leader 追数据
追上 HW → 重新加入 ISR7.2 Leader 故障
处理流程:
选出新 Leader(从 ISR)
新 Leader 保持原 HW
消费者从原 HW 继续读
旧 Leader 恢复后变 Follower 追数据7.3 副本同步监控
| 监控指标 | 说明 |
|---|---|
| ISR 数量 | 收缩表示同步异常 |
| UnderReplicatedPartitions | 副本不足的分区数 |
| ISR 膨胀/收缩频率 | 集群稳定性 |
八、常见问题与排查
8.1 ISR 频繁收缩
原因:
磁盘 IO 慢(同盘竞争)
网络抖动
分区数过多(拉取线程不够)
垃圾回收停顿
排查:
检查磁盘/网络指标
增加 num.replica.fetchers
分散分区8.2 写入时好时坏
现象:
有时超时,有时正常
原因:
ISR 收缩触发 Min ISR 拒绝
Leader 频繁切换
处理:
看 ISR 收缩原因
稳定集群避免选举风暴8.3 消息丢失风险点
| 场景 | 防护 |
|---|---|
| acks=0/1 | 调高 acks |
| unclean 选举 | 关闭该配置 |
| 副本因子=1 | 至少 2 副本 |
| 生产者重试不开启 | 开启 retries |
九、小结
副本机制回答三个问题:数据存几份(副本)、哪些算同步(ISR)、写多稳(Ack + Min ISR)。核心权衡是可靠性与可用性:ISR 保证不选落后副本当 Leader,Min ISR + Ack 保证写入有最低确认。生产环境记住"acks=all + min.insync.replicas=2 + 关闭 unclean"这套黄金组合。