摘要
本文总结了 Kafka 的实战经验,重点探讨了 Kafka 的分区副本机制、ISR 与非 ISR 节点的概念及作用、Leader 选举流程以及与 ZooKeeper 的关系等内容,旨在帮助读者深入理解 Kafka 的工作原理和高可用性保障机制,提升在大数据存储域中使用 Kafka 的能力。

1. kafka使用zk存储哪些数据?
Kafka 使用 ZooKeeper 主要存储 集群元数据、topic/partition 配置、controller 选举信息、broker 状态 。Kafka 0.9 之前还会存储 消费者组信息和消费 offset,但之后这些都移到了 Kafka 内部。
|---------------|----------------------------------------------------|------------------|
| 类别 | ZooKeeper 路径示例 | 存储内容 |
| Broker 信息 | /brokers/ids/[brokerId]
| broker 地址、端口、版本等 |
| Controller 信息 | /controller
| 当前控制器的 brokerId |
| Topic 配置 | /config/topics/[topicName]
| topic 副本数、分区数等配置 |
| Partition 元数据 | /brokers/topics/[topic]/partitions/[partitionId]
| 分区副本、ISR、leader |
| Consumer 旧版信息 | /consumers/[groupId]/ids/[consumerId]
| 消费者成员信息 |
| Offset 旧版 | /consumers/[groupId]/offsets/[topic]/[partition]
| 消费 offset |
| Broker 配置 | /config/brokers/[brokerId]
| 动态 broker 配置 |
| 管理操作 | /admin/reassign_partitions
| 分区迁移任务 |
| | /admin/preferred_replica_election
| 优先副本 leader 选举 |
1.1. 集群级别的元数据
- broker 注册信息:
/brokers/ids/[brokerId]
-
- 保存每个 broker 的地址、端口、版本等信息。
- broker 启动时向 ZK 注册,宕机时节点消失。
- 集群元信息:
/brokers/seqid
-
- 用来给 broker 分配唯一 ID。
- Kafka Controller 信息:
/controller
-
- 保存当前 controller(控制器)的 brokerId。
- Controller 负责分区 leader 选举、broker 状态管理。
1.2. Topic/Partition 元数据
- Topic 配置:
/config/topics/[topicName]
-
- 存储 topic 的副本数、副本因子、分区数等配置信息。
- Partition 分布信息:
/brokers/topics/[topicName]/partitions/[partitionId]
-
- 记录该分区有哪些副本(replica),这些副本在哪些 broker 上。
- Partition Leader 信息:
/brokers/topics/[topicName]/partitions/[partitionId]/state
-
- 当前 leader 是哪个 broker,ISR(in-sync replicas,同步副本集合)有哪些。
1.3. 消费者相关信息(Kafka 0.9 之前)
注意:Kafka 0.9 之后引入了新的Consumer API,消费offset 存在 Kafka 内部的 __consumer_offsets****topic 中,不再依赖 ZK。
- Consumer Group信息:
/consumers/[groupId]/ids/[consumerId]
-
- 记录某个消费者组里的消费者成员。
- 消费进度(旧版):
/consumers/[groupId]/offsets/[topic]/[partitionId]
-
- 存储该 group 在某个 topic 的 partition 上的消费 offset。
1.4. 配置数据
- Broker 配置:
/config/brokers/[brokerId]
-
- 存储 broker 的动态配置(某些参数可以动态更新)。
- Topic 配置(覆盖):
/config/topics/[topicName]
-
- 存储 topic 的自定义配置(覆盖 broker 默认配置)。
1.5. 临时/协调数据
- Reassign Partitions:
/admin/reassign_partitions
-
- 用于分区迁移(手动触发时)。
- Preferred Replica Election:
/admin/preferred_replica_election
-
- 触发分区 leader 重新选举为优先副本。
- ACL 权限:
/kafka-acl
-
- 保存 Kafka 的访问控制列表(ACLs)。
2. Controller是kafka什么角色?
Kafka 里的 Controller(控制器) 是 Kafka 集群中一个 特殊的 Broker 角色,用来管理集群元数据和分区状态。
2.1. Controller 的定义
Kafka 集群里所有的 broker 都有能力成为 Controller。通过 ZooKeeper(旧架构) 或 KRaft(新架构) 来选举出唯一一个 Controller。一旦选出,Controller 负责协调整个集群的运行,比如 分区 Leader 选举、broker 宕机处理、分区迁移 等。可以理解为:
- 普通 broker:负责存储消息、处理生产/消费请求。
- Controller broker:负责调度和管理这些 broker 的"分工"。
2.2. Controller 的主要职责
- 分区 Leader 选举
- 当一个分区的 leader 宕机时,Controller 负责在 ISR(in-sync replicas,同步副本集合)中选出新的 leader,并通知相关 broker。
- 确保消息读写不间断。
- Broker 状态管理
- 监控 broker 的加入和退出。
- 如果检测到 broker 宕机,触发分区 leader 迁移。
- 集群元数据管理
- 维护 topic、分区、副本、ISR 等信息。
- 将这些元数据通过 元数据更新请求(UpdateMetadataRequest)下发给所有 broker。
- 分区迁移 & 优先副本选举
- 当管理员触发
reassign-partitions.sh
时,由 Controller 负责执行迁移。 - 也可以执行"优先副本选举",让 leader 回到指定的优先副本上。
2.3. Controller的选举方式
- ZooKeeper 模式(旧版 Kafka < 2.8)
-
- 所有 broker 去 ZK 的
/controller
节点争抢写入,谁成功写入谁就是 Controller。 - 如果 Controller 宕机,ZK 节点消失,其它 broker 重新抢占,触发新的选举。
- 所有 broker 去 ZK 的
- KRaft 模式(Kafka 2.8+,无 ZK)
-
- 通过 Raft 协议 在 broker 内部选举出 Controller。
- KRaft 模式下 Controller 通常运行在专门的 Controller Quorum(控制器仲裁节点) 上。
2.4. Controller的高可用机制
- Kafka 集群只有 一个活跃的 Controller,避免元数据混乱。
- 其它 broker 是"候选者",一旦当前 Controller 挂掉,就会快速触发新选举。
- 这种机制保证了 Kafka 集群的 高可用和快速故障恢复。
3. Kafka 集群里 Controller 是不是broker集群中 master 节点?
Kafka 的 Controller 可以类比为 master 节点,但它并不是一个 专职 master,更像是 broker 集群里临时选出的"领导"。
- 传统 master/worker 架构:master 负责调度、worker 负责执行,master 掉了可能整个系统就瘫痪。
- Kafka 架构:Controller = broker 中的"队长",只在元数据变化时发挥作用。大多数时间它和普通 broker 一样在存储消息。如果挂了,立刻换一个 broker 当"队长",整个集群消息读写几乎不受影响。
3.1. 相似点(像 master 的地方)
- 唯一性 :在一个 Kafka 集群里,同时只有一个活跃的 Controller,类似 master 节点。
- 调度管理角色 :Controller 负责 分区 leader 选举、broker 状态管理、元数据分发,就像 master 在负责调度整个集群。
- 选举机制:Controller 通过 ZK(老版本)或 Raft(新版本)选举产生,和 master 节点选举的思路类似。
3.2. 不同点(不像 master 的地方)
- Controller 也是 Broker
-
- 它既能存储消息、处理生产和消费请求,也能承担控制职责。
- 并不是"专门的 master 节点",而是 普通 broker 中临时选出的一个"兼任管理"的节点。
- 没有强中心化调度
-
- 在传统 master/worker 架构里,worker 的任务分配通常由 master 下发。
- 而在 Kafka 中,消息的生产和消费不需要 Controller 参与 ,Controller 只在 元数据发生变化(比如 broker 宕机、分区 leader 变化)时才介入。
- 日常的数据读写,生产者和消费者是直接和分区 leader broker 通信的。
- 故障转移非常轻量
-
- 如果 Controller 挂了,会立刻重新选一个 broker 作为新的 Controller。
- Kafka 并不会因为 Controller 宕机而导致整个集群不可用,只是元数据操作会短暂受影响。
4. kafka为什么需要使用zk ,什么版本之后就不使用zk了?
Kafka 设计之初(0.x ~ 2.x),依赖 ZooKeeper 来做集群的 元数据管理和协调。主要作用:
- **集群成员管理:**哪些broker存活、加入、退出,由 ZK 负责维护。
- **Topic 元数据存储:**topic 的分区、副本、副本所在 broker 等信息放在ZK中。
- **Controller 选举:**Kafka 需要一个控制器(Controller)来负责分区的leader 选举、副本管理等,这个角色通过 ZK 选举产生。
- **分区 Leader 选举:**当某个 broker 宕机时,ZK 负责协调选举新的 leader,保证高可用。
总结:ZooKeeper 在 Kafka 中相当于"大脑+协调员",Kafka 本身只专注在消息存储和消费。
随着 Kafka 大规模应用,ZooKeeper 的一些问题逐渐暴露出来:
- **运维复杂:**Kafka 集群 + ZooKeeper 集群 = 双集群运维,难度增加。
- **一致性延迟:**Kafka 内部状态变化(如 leader 选举)依赖 ZK,同步有延迟,可能导致故障恢复不够快。
- **扩展性瓶颈:**ZK 的 watch 机制在大规模 topic/partition 下,负担很大。
- **职责分散:**集群元数据分散在 Kafka 和 ZK,不利于统一管理。
Kafka 社区希望通过引入自管理元数据(KRaft 模式) ,彻底去掉 ZK,使 Kafka 更独立、更高效。KRaft = Kafka + Raft 协议 (共识协议,类似于 etcd、consul 使用的)。
优势:
- 不依赖外部组件,Kafka 自己就能完成元数据管理。
- 更快的控制器选举(毫秒级,而 ZK 可能是秒级)。
- 单一存储 :所有元数据存在 Kafka 内部的
__cluster_metadata
topic,不再分散在 ZK。 - 更好扩展性:支持百万级 partition。
- 简化运维:只需运维 Kafka,不需要额外维护 ZooKeeper。
5. Kafka 不使用zk存储数据之后, broker中数据怎能存储和管理?
5.1. Kafka 以前为什么依赖 ZooKeeper?
在 ZK模式 下:
- 元数据(broker 列表、topic 配置、分区信息、ISR 集合、Controller 选举结果等)存储在 ZooKeeper。
- Kafka broker 自己只存储业务数据(消息 log segment 文件)。
这样导致 Kafka 的运行依赖外部组件(ZK),架构复杂。
5.2. 去掉 ZK 之后元数据存储在哪里?
在KRaft 模式 (Kafka Raft Metadata 模式)下,Kafka 引入了一个内置的元数据日志(metadata log):
- 所有元数据都写入一个特殊的内部 topic:
__cluster_metadata
。 - 这个topic 的日志文件存在 broker的本地磁盘 (跟消息日志一样,默认在
log.dirs
目录下)。 - 它是一个 Raft 共识日志 ,由 Controller quorum(控制器仲裁节点) 维护。
这样就不需要 ZooKeeper 了,Kafka自己保证元数据的一致性和高可用。
5.3. 元数据管理的方式(KRaft 模式)
- Controller quorum
-
- Kafka 集群中会有一组 broker 充当 Controller 节点(专门用于管理元数据,不处理业务流量)。
- 它们使用 Raft 协议 选出一个 leader controller,负责接收元数据更新请求。
- 元数据写入
-
- 比如创建 topic、修改分区、副本迁移等操作,都会被写入
__cluster_metadata
这个日志。 - Raft 协议保证这个日志在 controller quorum 内达成一致。
- 比如创建 topic、修改分区、副本迁移等操作,都会被写入
- 元数据下发
-
- Controller leader 将新的元数据通过网络推送给所有 broker。
- Broker 在本地更新自己的缓存,并持久化到磁盘。
- Broker 启动时同步
-
- 新加入的 broker 启动后,会从 Controller leader 获取最新的元数据快照,保证和集群保持一致。
5.4. 数据存储划分
在 KRaft 模式下,Kafka 的存储可以分为两类:
- 业务数据(消息日志)
-
- 每个 broker 仍然用 分区副本机制 存储消息。
- 这些数据文件存在
log.dirs
(例如/kafka-logs/topic-partition/
)。
- 集群元数据(metadata log)
-
- 存在
__cluster_metadata
内部 topic。 - 文件结构和普通 topic 一样(log segment + index),但内容是集群配置、topic 定义、副本信息等。
- 由 Controller quorum 管理。
- 存在
6. kafka集群其中一个borker宕机了?怎么提供服务?
因为 Kafka 的高可用(HA)就是靠 分区副本机制 + Controller 协调 来实现的。
6.1. Kafka 的分区副本机制(前提)
- Kafka 的 Topic 会被划分成多个 Partition(分区)。
- 每个 Partition 有 一个 Leader 副本 和 若干个 Follower 副本。
- 生产者(Producer)和消费者(Consumer) 都只和Leader副本交互。
- Follower负责从Leader 异步复制消息 ,形成 ISR(In-Sync Replicas,同步副本集合)。
6.2. Broker 宕机时的处理
假设 Kafka 集群里有一个 Broker 宕机了:
- 如果宕机的Broker不是任何分区的Leader
- 影响:几乎没有影响。
- 其他Broker 上的 Leader 仍然可以提供读写服务。
- Controller 只是更新一下元数据,把这个 Broker 标记为失效。
- 如果宕机的 Broker 上有分区 Leader
- Controller 会感知到 Broker 宕机(通过 ZooKeeper 或 KRaft)。
- 在 ISR 中找到这些分区的 可用 Follower,并将其中一个提升为新的 Leader。
- 把新的 Leader 信息更新到元数据,并通知所有 Producer/Consumer。
- Producer/Consumer 之后的请求会路由到新的Leader。
- 如果宕机的 Broker上既有Leader又有Follower
- 它作为 Follower 的副本也会丢失。
- ISR 会自动把这个 Broker 移除。
- 当它恢复后,会从当前 Leader 追赶(catch up) 数据,重新加入 ISR。
6.3. 保障机制
- Replication Factor(副本数):
-
- 如果一个分区只有 1 个副本(RF=1),且 Leader 宕机 → 这个分区就不可用。
- 所以生产环境一般 RF ≥ 3。
- min.insync.replicas:
-
- 限制消息必须写入多少个副本才算成功,保证数据可靠性。
- Unclean Leader Election:
-
- 如果 ISR 都不可用,可以允许落后副本当 Leader(可能丢数据)。
- 配置:
unclean.leader.election.enable
(默认 false,生产环境建议关闭)。
7. Partition 中leader 和flower 是什么管理? 消费这是连接leader 还是?
7.1. Partition 中的 Leader 和 Follower 管理
- Leader
-
- 一个分区(Partition)中,只能有一个 Leader 副本。
- 负责该分区的所有 读写请求(生产者写消息,消费者读消息)。
- Follower
-
- 作为 Leader 的备份副本。
- 只从 Leader 拉取(同步)数据,保证和 Leader 数据一致。
- 不直接对外提供读/写服务。
7.2. 管理机制
- Controller(控制器) 负责分区 Leader 的管理:
-
- Leader 选举:当分区创建、或者原 Leader 宕机时,Controller 负责从 ISR 中选一个 Follower 当新的 Leader。
- ISR 管理:Controller 跟踪每个 Partition 的 ISR(In-Sync Replicas,同步副本集合),保证 Leader 有足够的"可靠备份"。
- 元数据下发:Controller 把 Leader/ISR 变化通知所有 Broker,让它们更新路由信息。
7.3. Producer / Consumer 访问路径
- Producer(生产者):只写 Leader :生产者发送消息时,会查询元数据(由 Broker 返回),找到分区的 Leader Broker,然后把消息写给它。Follower 不接收写请求,它们只被动同步。
- Consumer(消费者):只读 Leader :消费者拉取消息时,也只会连接到 Leader Broker。Follower 不提供读服务(虽然理论上能读,但 Kafka 默认禁止,避免数据不一致)。
7.4. 为什么只能访问 Leader?
原因:保证数据一致性和顺序性。
- 如果允许读 Follower,可能会读到滞后的数据(因为复制是异步的)。
- Kafka 需要保证消息 单分区内的顺序,由 Leader 统一控制更简单。
(不过 Kafka 社区里有个方向:Follower Fetching 或 Read Replica,允许从 Follower 读取以减轻 Leader 压力,但默认没启用,只有特殊场景会考虑。)
8. Partition中的Leader宕机了,会重新从flower中选新的leader吗?
在 Kafka 中,如果 Partition 的 Leader 宕机 ,就会从 Follower 副本中选举新的 Leader。
8.1. 故障检测
- Controller(集群控制器)会监控所有 Broker 的心跳。
- 当某个 Broker 宕机时,Controller 会立刻感知(通过 ZK 模式 或 KRaft 模式)。
- 如果这个Broker上有分区 Leader,Controller 就需要发起新的 Leader 选举。
8.2. Leader 选举流程
- 确认 ISR 集合
-
- ISR(In-Sync Replicas,同步副本集合)是指那些和 Leader 数据保持同步的副本。
- Controller 会检查这个 Partition 的 ISR 集合。
- 从 ISR 中选举新的 Leader
-
- 按照优先级(通常是副本列表的顺序)选择一个 Follower。
- 把它提升为新的 Leader。
- 元数据更新
-
- Controller 更新集群元数据(哪台 Broker 是新 Leader)。
- 把新的 Leader 信息下发给所有 Broker。
- 客户端自动切换
-
- Producer / Consumer 在请求失败后,会刷新元数据,自动连接到新的 Leader。
8.3. 特殊情况:没有同步副本
-
如果 ISR 里已经没有可用副本了,会涉及一个配置:
unclean.leader.election.enable
-
false(默认,推荐生产环境):不允许从非 ISR 选 Leader。这样能保证数据不丢,但分区会暂时不可用(相当于"宁可等,不丢数据")。
-
true(风险较高):允许从非 ISR(落后副本)选 Leader。这样可以让分区继续可用,但可能导致数据丢失或回退。
8.4. 举例说明
假设 Topic orders
的 Partition-0 有 3 个副本:
- Leader:Broker-1
- Follower:Broker-2, Broker-3
- ISR = {Broker-1, Broker-2, Broker-3}
如果 Broker-1 宕机:
- Controller 检测到 Broker-1 宕机。
- 从 ISR 中选一个(比如 Broker-2)作为新的 Leader。
- 更新元数据,Producer / Consumer 自动切到 Broker-2。
- Broker-3 继续作为 Follower。
9. ISR(In-Sync Replicas) 和 非 ISR节点
9.1. ISR(In-Sync Replicas,同步副本集合)
指的是:和 Leader 数据保持同步的副本。
条件:
- 副本必须存活(Broker 还在运行)。
- 副本的消息追赶进度没有落后太多,能跟上 Leader 的数据写入。
作用:Kafka 只会在 ISR 内选 Leader,这样保证新Leader的数据不会丢。
9.2. 非 ISR(Out-of-Sync Replicas,落后副本)
指的是:副本还在集群里,但数据落后太多,追不上 Leader。
特征:
- Broker 宕机恢复后,副本会落后 Leader 很多消息,直到同步赶上才能重新进 ISR。
- 网络慢、磁盘慢、或 GC 卡顿,也可能导致副本落后而被踢出 ISR。
它们仍然保存数据,但因为不保证数据完整性,不能直接当 Leader。
9.3. 举个例子
假设一个分区有 3 个副本:
- Leader:Broker-1
- Follower:Broker-2, Broker-3
**正常情况:**Broker-2 和 Broker-3 紧跟 Leader,ISR = {1,2,3}
Broker-2 网络很慢,落后太多:
- ISR = {1,3}
- Broker-2 就成了 非 ISR(out-of-sync 副本)
如果这时 Leader 宕机:
- 只能在 ISR = {1,3} 中选新的 Leader → Broker-3
- Broker-2 因为不在 ISR,就不会被选为 Leader。
博文参考
- 《Kafka原理》
- 《大数据存储域》