Kafka 副本机制
副本架构
Kafka 为每个 Partition 维护多份副本,分布在不同的 Broker 上,实现高可用和数据不丢失。
Topic "orders", Partition 0, Replication Factor = 3
┌─────────────────────────┐
│ Broker 1 │
│ ┌─────────────────┐ │
│ │ Leader (P0) │ │ ← 所有读写
│ │ Offset 0..999 │ │
│ └─────────────────┘ │
└──────────┬──────────────┘
│ 数据同步
┌──────────▼──────────────┐
│ Broker 2 │
│ ┌─────────────────┐ │
│ │ Follower (P0) │ │
│ │ Offset 0..998 │ │ ← ISR
│ └─────────────────┘ │
└──────────┬──────────────┘
│
┌──────────▼──────────────┐
│ Broker 3 │
│ ┌─────────────────┐ │
│ │ Follower (P0) │ │
│ │ Offset 0..950 │ │ ← lag=49, 不在 ISR
│ └─────────────────┘ │
└─────────────────────────┘关键概念
| 概念 | 说明 |
|---|---|
| Leader | 负责该 Partition 的所有读写,每个 Partition 只有一个 Leader |
| Follower | 被动从 Leader 拉取并同步数据,不处理客户端请求 |
| ISR (In-Sync Replicas) | 与 Leader 保持同步的副本集合,能及时追上 Leader 的写入 |
| OSR (Out-of-Sync Replicas) | 已落后于 Leader(replica.lag.time.max.ms 阈值)的副本 |
| HW (High Watermark) | ISR 中所有副本都已写入的最小 Offset,Consumer 最多读到 HW |
| LEO (Log End Offset) | 副本已写入的最新 Offset(含未提交) |
ISR 判定
shell
# 查看 ISR 状态
kafka-topics.sh --describe --topic orders --bootstrap-server localhost:9092
# Partition: 0 Leader: 1 Replicas: 1,2,3 Isr: 1,2 (3 掉出 ISR)Follower 掉出 ISR 的条件:副本 LEO 落后 Leader LEO 的时间 > replica.lag.time.max.ms(默认 30s)。
v2.5 前还有一个基于消息数的 lag 判断(
replica.lag.max.messages),现已移除。
Leader 选举
当 Leader 故障时,Kafka Controller 从 ISR 列表中选择新的 Leader。
选举流程
Broker 1 (Leader) × 故障
│
▼
Controller (Broker 2) 检测到 Broker 1 不可用
│
├── 从 Partition 0 的 ISR [1, 2, 3] 中排除 1
├── 选择 ISR 中第一个可用副本 ← Broker 2
│
└── 广播 LeaderAndIsr 请求,新 Leader = Broker 2Unclean Leader Election
当 ISR 为空(所有副本都挂了或掉出 ISR)时,是否允许从 OSR 中选 Leader:
| 配置 | 行为 | 风险 |
|---|---|---|
unclean.leader.election.enable=false(默认) | 等待 ISR 副本恢复 | 这段时间 Partition 不可用 |
unclean.leader.election.enable=true | 从 OSR 选 Leader,尽快恢复 | 丢数据(OSR 未同步的消息丢失) |
生产环境建议保持
false,优先一致性。
副本同步机制
Producer ──write──► Leader (Broker 1)
│
├── 写入本地日志 (LEO+1)
│
├── Follower (Broker 2) ──fetch──► 拉取数据
│ ├── 写入本地日志 (LEO+1)
│ └── 告知 Leader 已同步
│
├── Follower (Broker 3) ──fetch──► 拉取数据
│ └── 同上
│
└── 所有 ISR 确认 (acks=all)
└── HW 推进 → Consumer 可消费核心配置
| 参数 | 默认值 | 说明 |
|---|---|---|
replication.factor | 1 | Topic 级别副本数(Broker 级 default.replication.factor) |
min.insync.replicas | 1 | Topic/Broker 级最小 ISR 数 |
replica.lag.time.max.ms | 30000(30s) | Follower 与 Leader 的最大同步延迟 |
replica.fetch.max.bytes | 1MB | Follower 每个 Fetch 请求的最大字节数 |
replica.fetch.wait.max.ms | 500 | Follower 等待新数据的最大时间 |
unclean.leader.election.enable | false | 是否允许 OSR 副本选为 Leader |
num.replica.fetchers | 1 | Follower 拉取线程数(调大可加速同步) |
min.insync.replicas 与 acks=all
java
// 安全配置:避免 Leader 单点故障导致数据丢失
// acks=all + min.insync.replicas=2 + replication.factor=3
props.put("acks", "all");
props.put("min.insync.replicas", "2");
props.put("replication.factor", "3");| replication.factor | min.insync.replicas | 容忍故障 Broker 数 | 数据安全 |
|---|---|---|---|
| 3 | 1 | 2 | 低(Leader 写入即返回,Follower 可能全挂) |
| 3 | 2 | 1 | 高(至少 1 个 Follower 确认) |
| 3 | 3 | 0 | 最高(全确认,但任一 Broker 故障则写入阻塞) |
副本管理
shell
# 查看副本分布和 ISR 状态
kafka-topics.sh --describe --topic orders --bootstrap-server localhost:9092
# 查看 Topic 副本分布
kafka-replica-verification.sh --broker-list localhost:9092
# 查看 Under-Replicated Partitions
kafka-metadata-quorum.sh --describe --status --bootstrap-server localhost:9092Controller 角色
Controller 是 Kafka 集群中负责管理 Partition 和副本状态的 Broker:
| 职责 | 说明 |
|---|---|
| Leader 选举 | 检测 Broker 故障,从 ISR 中选择新 Leader |
| ISR 管理 | 决定 Follower 进入/退出 ISR |
| Partition 分配 | 新 Topic / 扩容时分配 Partition 到 Broker |
| 元数据广播 | 将 Leader/ISR 变更广播到所有 Broker |
Controller 选举(KRaft 模式)由 KRaft Quorum Leader 担任,ZK 模式下由 ZooKeeper 进行 Broker 间的 Controller 选举。