Kafka + ZooKeeper架构基础介绍
一、整体架构
ZooKeeper 是 Kafka 2.8 之前的必选协调组件,只做集群管控,不参与消息读写:
- 存储集群元数据(Broker、Topic、分区、副本、ISR 信息)
- 提供分布式锁与临时节点,实现 Kafka Controller 选举
- 感知 Broker 上下线
- 持久化分区 Leader 状态
Kafka 只负责:消息接收、存储、复制、消费。
二、ZooKeeper 在 Kafka 中的核心作用
1. 存储的关键元数据(ZK 节点路径)
| /brokers/ids/[brokerId] | Broker 注册临时节点,标记存活 |
| /brokers/topics/[topic] | 主题的分区数、副本分配方案 |
| /brokers/topics/[topic]/partitions/[N]/state | 分区状态:Leader、ISR、副本集合 |
| /controller | 保存当前 Controller 信息(临时节点) |
| /config/topics/[topic] | 主题级配置 |
| /admin/delete_topics | 待删除主题队列 |
2. 四大核心职责
Broker 注册与健康检测
- Broker 启动 → 创建临时节点 /brokers/ids/xx
- 断开连接 → 节点自动删除 → Kafka 感知下线。
Kafka Controller 选举
- 所有 Broker 争抢创建 /controller 临时节点,成功即为 Controller。
分区 Leader 状态持久化
- 每次 Leader 变更,结果写入 ZooKeeper,保证全局一致。
集群统一视图
- 所有 Broker 共享同一份元数据,不会出现脑裂。
三、ZooKeeper 配置(供 Kafka 使用)
zoo.cfg 完整配置
# 基础时间单位 ms
tickTime=2000
initLimit=10
syncLimit=5
# 数据目录(生产必须独立磁盘)
dataDir=/data/zookeeper/data
dataLogDir=/data/zookeeper/log
clientPort=2181
# Kafka 集群需要高连接数
maxClientCnxns=2000
# 自动清理快照与日志
autopurge.snapRetainCount=5
autopurge.purgeInterval=24
# ZK 集群(3 节点示例)
server.1=zk1:2888:3888
server.2=zk2:2888:3888
server.3=zk3:2888:3888
关键配置说明
- dataDir:ZK 内存数据快照目录
- dataLogDir:事务日志目录(必须独立磁盘,性能关键)
- maxClientCnxns:Kafka 集群需调高,避免连接被拒
- autopurge:防止日志占满磁盘
节点标识(必须配置)
echo "1" > /data/zookeeper/data/myid
myid 必须与 server.1/2/3 中的数字一致。
四、Kafka 连接 ZooKeeper 核心配置
server.properties 关键配置
# 唯一标识
broker.id=1
# 监听地址
listeners=PLAINTEXT://0.0.0.0:9092
advertised.listeners=PLAINTEXT://192.168.1.101:9092
# 日志存储
log.dirs=/data/kafka/logs
num.partitions=8
default.replication.factor=3
min.insync.replicas=2
# ======================
# ZK 核心配置
# ======================
zookeeper.connect=zk1:2181,zk2:2181,zk3:2181/kafka
zookeeper.connection.timeout.ms=10000
zookeeper.session.timeout.ms=18000
# 生产关闭自动创建主题
auto.create.topics.enable=false
delete.topic.enable=true
重点说明
- zookeeper.connect 末尾 /kafka 是命名空间,用于多集群隔离
- zookeeper.session.timeout.ms:超时即认为 Broker 已下线
- min.insync.replicas:最小同步副本数,保证数据不丢失
五、Kafka 分区主从机制:Leader / Follower / ISR
1. 主从角色
- Leader:每个分区只有一个,负责读写
- Follower:只从 Leader 同步数据,不提供读写
- ISR(In-Sync Replicas):与 Leader 保持同步的副本集合
2. 核心规则
- 生产者、消费者只与 Leader 交互
- Follower 异步拉取消息
- 只有 ISR 内的副本才有资格被选为新 Leader
3. 高可用保证
- Leader 宕机 → 从 ISR 中选新 Leader
- 配置 acks=all + min.insync.replicas=2 可保证消息不丢失
六、Kafka Controller 选举流程(基于 ZK)
1. Controller 是什么?
集群中唯一的管理节点,负责:
- 分区 Leader 选举
- 副本分配与重分配
- 感知 Broker 上下线
- 同步元数据给所有 Broker
2. 选举流程(完全依赖 ZooKeeper)
ZooKeeperBroker 3Broker 2Broker 1ZooKeeperBroker 3Broker 2Broker 1#mermaid-svg-rRsd8m7GDXMf1Gbt{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rRsd8m7GDXMf1Gbt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rRsd8m7GDXMf1Gbt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rRsd8m7GDXMf1Gbt .error-icon{fill:#552222;}#mermaid-svg-rRsd8m7GDXMf1Gbt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rRsd8m7GDXMf1Gbt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rRsd8m7GDXMf1Gbt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rRsd8m7GDXMf1Gbt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rRsd8m7GDXMf1Gbt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rRsd8m7GDXMf1Gbt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rRsd8m7GDXMf1Gbt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rRsd8m7GDXMf1Gbt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rRsd8m7GDXMf1Gbt .marker.cross{stroke:#333333;}#mermaid-svg-rRsd8m7GDXMf1Gbt svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rRsd8m7GDXMf1Gbt p{margin:0;}#mermaid-svg-rRsd8m7GDXMf1Gbt .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-rRsd8m7GDXMf1Gbt text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-rRsd8m7GDXMf1Gbt .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-rRsd8m7GDXMf1Gbt .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-rRsd8m7GDXMf1Gbt .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-rRsd8m7GDXMf1Gbt .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-rRsd8m7GDXMf1Gbt #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-rRsd8m7GDXMf1Gbt .sequenceNumber{fill:white;}#mermaid-svg-rRsd8m7GDXMf1Gbt #sequencenumber{fill:#333;}#mermaid-svg-rRsd8m7GDXMf1Gbt #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-rRsd8m7GDXMf1Gbt .messageText{fill:#333;stroke:none;}#mermaid-svg-rRsd8m7GDXMf1Gbt .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-rRsd8m7GDXMf1Gbt .labelText,#mermaid-svg-rRsd8m7GDXMf1Gbt .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-rRsd8m7GDXMf1Gbt .loopText,#mermaid-svg-rRsd8m7GDXMf1Gbt .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-rRsd8m7GDXMf1Gbt .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-rRsd8m7GDXMf1Gbt .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-rRsd8m7GDXMf1Gbt .noteText,#mermaid-svg-rRsd8m7GDXMf1Gbt .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-rRsd8m7GDXMf1Gbt .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-rRsd8m7GDXMf1Gbt .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-rRsd8m7GDXMf1Gbt .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-rRsd8m7GDXMf1Gbt .actorPopupMenu{position:absolute;}#mermaid-svg-rRsd8m7GDXMf1Gbt .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-rRsd8m7GDXMf1Gbt .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-rRsd8m7GDXMf1Gbt .actor-man circle,#mermaid-svg-rRsd8m7GDXMf1Gbt line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-rRsd8m7GDXMf1Gbt :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}所有 Broker 启动B1 宕机(网络断开)create /controller (ephemeral)成功 → B1 成为 Controllercreate /controller → 失败watch /controllercreate /controller → 失败watch /controllerSession 超时(~6s)删除 /controller 节点Watch 触发create /controller → 成功 → B2 成为新 Controller
特点:抢占式、简单、强依赖 ZK 临时节点特性。
七、Kafka 分区 Leader 选举流程
触发时机
- Broker 宕机
- 分区重分配
- 集群启动/停止
完整流程
#mermaid-svg-4w4hRaYqRAjcGqT8{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-4w4hRaYqRAjcGqT8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-4w4hRaYqRAjcGqT8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-4w4hRaYqRAjcGqT8 .error-icon{fill:#552222;}#mermaid-svg-4w4hRaYqRAjcGqT8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4w4hRaYqRAjcGqT8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-4w4hRaYqRAjcGqT8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4w4hRaYqRAjcGqT8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4w4hRaYqRAjcGqT8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-4w4hRaYqRAjcGqT8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4w4hRaYqRAjcGqT8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4w4hRaYqRAjcGqT8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4w4hRaYqRAjcGqT8 .marker.cross{stroke:#333333;}#mermaid-svg-4w4hRaYqRAjcGqT8 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4w4hRaYqRAjcGqT8 p{margin:0;}#mermaid-svg-4w4hRaYqRAjcGqT8 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-4w4hRaYqRAjcGqT8 .cluster-label text{fill:#333;}#mermaid-svg-4w4hRaYqRAjcGqT8 .cluster-label span{color:#333;}#mermaid-svg-4w4hRaYqRAjcGqT8 .cluster-label span p{background-color:transparent;}#mermaid-svg-4w4hRaYqRAjcGqT8 .label text,#mermaid-svg-4w4hRaYqRAjcGqT8 span{fill:#333;color:#333;}#mermaid-svg-4w4hRaYqRAjcGqT8 .node rect,#mermaid-svg-4w4hRaYqRAjcGqT8 .node circle,#mermaid-svg-4w4hRaYqRAjcGqT8 .node ellipse,#mermaid-svg-4w4hRaYqRAjcGqT8 .node polygon,#mermaid-svg-4w4hRaYqRAjcGqT8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4w4hRaYqRAjcGqT8 .rough-node .label text,#mermaid-svg-4w4hRaYqRAjcGqT8 .node .label text,#mermaid-svg-4w4hRaYqRAjcGqT8 .image-shape .label,#mermaid-svg-4w4hRaYqRAjcGqT8 .icon-shape .label{text-anchor:middle;}#mermaid-svg-4w4hRaYqRAjcGqT8 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-4w4hRaYqRAjcGqT8 .rough-node .label,#mermaid-svg-4w4hRaYqRAjcGqT8 .node .label,#mermaid-svg-4w4hRaYqRAjcGqT8 .image-shape .label,#mermaid-svg-4w4hRaYqRAjcGqT8 .icon-shape .label{text-align:center;}#mermaid-svg-4w4hRaYqRAjcGqT8 .node.clickable{cursor:pointer;}#mermaid-svg-4w4hRaYqRAjcGqT8 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-4w4hRaYqRAjcGqT8 .arrowheadPath{fill:#333333;}#mermaid-svg-4w4hRaYqRAjcGqT8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-4w4hRaYqRAjcGqT8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-4w4hRaYqRAjcGqT8 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4w4hRaYqRAjcGqT8 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-4w4hRaYqRAjcGqT8 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4w4hRaYqRAjcGqT8 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-4w4hRaYqRAjcGqT8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-4w4hRaYqRAjcGqT8 .cluster text{fill:#333;}#mermaid-svg-4w4hRaYqRAjcGqT8 .cluster span{color:#333;}#mermaid-svg-4w4hRaYqRAjcGqT8 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-4w4hRaYqRAjcGqT8 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-4w4hRaYqRAjcGqT8 rect.text{fill:none;stroke-width:0;}#mermaid-svg-4w4hRaYqRAjcGqT8 .icon-shape,#mermaid-svg-4w4hRaYqRAjcGqT8 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4w4hRaYqRAjcGqT8 .icon-shape p,#mermaid-svg-4w4hRaYqRAjcGqT8 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-4w4hRaYqRAjcGqT8 .icon-shape rect,#mermaid-svg-4w4hRaYqRAjcGqT8 .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4w4hRaYqRAjcGqT8 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-4w4hRaYqRAjcGqT8 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-4w4hRaYqRAjcGqT8 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Controller 监听到 Broker 下线
获取该 Broker 上所有 Leader 分区
遍历每个分区
查询该分区的 ISR 列表
选择第一个存活的副本作为新 Leader
更新 ZK 中的分区状态
广播新 Leader到所有 Broker
客户端开始访问新 Leader
详细步骤
- 读取该分区的 ISR 列表
- 选择 第一个存活的副本 作为新 Leader
/brokers/topics/[topic]/partitions/[x]/state
八、Kafka 主从同步机制
- 必须等 ISR 中所有副本 确认
- 才返回生产成功
九、常用运维命令(ZK + Kafka)
1. 查看当前 Controller
bin/zookeeper-shell.sh zk1:2181 get /controller
2. 查看主题详情(Leader / ISR)
bin/kafka-topics.sh –describe –topic test –bootstrap-server kafka1:9092
3. 查看在线 Broker
bin/zookeeper-shell.sh zk1:2181 ls /brokers/ids
4. 查看分区状态
bin/zookeeper-shell.sh zk1:2181 get /brokers/topics/test/partitions/0/state
十、关键故障机制
1. Broker 宕机
- ZK 会话超时 → /brokers/ids/xx 消失
- Controller 监听到 → 开始分区 Leader 迁移
2. Controller 宕机
- /controller 临时节点消失
- 所有 Broker 重新选举 Controller
- 新 Controller 从 ZK 加载全量元数据
3. ZK 不可用影响
- 已有的消息读写正常
- 无法创建/删除 Topic
- 无法重新选举 Controller、分区 Leader
- 无法上下线 Broker
网硕互联帮助中心






评论前必须登录!
注册