Kafka + ZooKeeper架构基础介绍

13 阅读4分钟

Kafka + ZooKeeper架构基础介绍

一、整体架构

ZooKeeper 是 Kafka 2.8 之前必选协调组件,只做集群管控,不参与消息读写:

  • 存储集群元数据(Broker、Topic、分区、副本、ISR 信息)
  • 提供分布式锁与临时节点,实现 Kafka Controller 选举
  • 感知 Broker 上下线
  • 持久化分区 Leader 状态

Kafka 只负责:消息接收、存储、复制、消费。


二、ZooKeeper 在 Kafka 中的核心作用

1. 存储的关键元数据(ZK 节点路径)

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. 四大核心职责

  1. Broker 注册与健康检测

    • Broker 启动 → 创建临时节点 /brokers/ids/xx
    • 断开连接 → 节点自动删除 → Kafka 感知下线。
  2. Kafka Controller 选举

    • 所有 Broker 争抢创建 /controller 临时节点,成功即为 Controller。
  3. 分区 Leader 状态持久化

    • 每次 Leader 变更,结果写入 ZooKeeper,保证全局一致。
  4. 集群统一视图

    • 所有 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)

sequenceDiagram
    participant B1 as Broker 1
    participant B2 as Broker 2
    participant B3 as Broker 3
    participant ZK as ZooKeeper

    Note over B1,B3: 所有 Broker 启动
    B1->>ZK: create /controller (ephemeral)
    ZK-->>B1: 成功 → B1 成为 Controller
    B2->>ZK: create /controller → 失败
    B2->>ZK: watch /controller
    B3->>ZK: create /controller → 失败
    B3->>ZK: watch /controller

    Note over B1,ZK: B1 宕机(网络断开)
    ZK->>ZK: Session 超时(~6s)
    ZK->>ZK: 删除 /controller 节点
    ZK->>B2: Watch 触发
    B2->>ZK: create /controller → 成功 → B2 成为新 Controller

特点:抢占式、简单、强依赖 ZK 临时节点特性。


七、Kafka 分区 Leader 选举流程

触发时机

  • Broker 宕机
  • 分区重分配
  • 集群启动/停止

完整流程

graph TD
    A[Controller 监听到 Broker 下线] --> B{获取该 Broker 上<br>所有 Leader 分区}
    B --> C{遍历每个分区}
    C --> D{查询该分区的 ISR 列表}
    D --> E{选择第一个存活的副本<br>作为新 Leader}
    E --> F{更新 ZK 中的<br>分区状态}
    F --> G{广播新 Leader<br>到所有 Broker}
    G --> H{客户端开始访问新 Leader}

详细步骤

  1. Controller 通过 ZK 监听到 Broker 下线
  2. 找到该 Broker 上所有 Leader 分区
  3. 对每个分区执行:
    • 读取该分区的 ISR 列表
    • 选择 第一个存活的副本 作为新 Leader
  4. 将新状态写入 ZK: /brokers/topics/[topic]/partitions/[x]/state
  5. Controller 把新元数据广播给所有 Broker
  6. 客户端开始访问新 Leader

八、Kafka 主从同步机制

  1. Follower 主动向 Leader 发起同步请求
  2. Leader 将消息写入后,同步给 Follower
  3. Follower 写入成功后回复 ACK
  4. 满足同步条件后加入 ISR
  5. 生产者 acks=all 时:
    • 必须等 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

十一、总结

  1. ZooKeeper:Kafka 集群的“配置中心 + 协调中心”。
  2. Broker 注册:依靠 ZK 临时节点实现存活检测。
  3. Controller 选举:争抢 ZK /controller 临时节点实现。
  4. 分区主从:Leader 提供读写,Follower 同步,ISR 保证高可用。
  5. Leader 选举:由 Controller 从 ISR 中选出,结果存入 ZK。
  6. ZK 作用边界:只管集群协调,不管消息收发。