欢迎光临
我们一直在努力

Zookeeper入门到实战详解

Zookeeper入门到实战:概念、集群、选举机制与常用命令全解析

前言

在学习Flink、Kafka、HBase等大数据组件的过程中,Zookeeper几乎是绕不开的基础组件。它在集群中负责协调各节点的状态、配置同步、服务注册等工作。本文基于尚硅谷Zookeeper V3.3教程,系统梳理Zookeeper的核心知识点,帮你真正搞清楚Zookeeper到底是什么、怎么用、面试怎么答。


一、Zookeeper是什么

Zookeeper是一个开源的分布式的,为分布式框架提供协调服务的Apache项目。

用一句话概括:Zookeeper = 文件系统 + 通知机制

从设计模式角度理解,Zookeeper是一个基于观察者模式设计的分布式服务管理框架:

  • 负责存储和管理大家都关心的数据
  • 接受观察者(客户端)的注册
  • 一旦数据状态发生变化,通知已注册的观察者做出响应

这个机制听起来很抽象,举个实际例子就清楚了:

服务端启动时 → 向Zookeeper注册信息(创建临时节点)
客户端 → 获取在线服务器列表,并注册监听
某服务端下线 → Zookeeper通知所有客户端
客户端收到通知 → 重新获取服务器列表,再次注册监听


二、Zookeeper的特点

  • Leader + Follower集群结构:一个集群由一个Leader和多个Follower组成

  • 半数存活即可服务:集群中只要有半数以上节点存活,就能正常提供服务。这也是为什么Zookeeper适合安装奇数台服务器(下文详细解释)

  • 全局数据一致:每个Server保存一份相同的数据副本,Client无论连接到哪个Server,读到的数据都是一致的

  • 更新请求顺序执行:来自同一个Client的更新请求按发送顺序依次执行

  • 数据更新原子性:一次数据更新要么全部成功,要么全部失败

  • 实时性:在一定时间范围内,Client能读到最新数据

  • 为什么要安装奇数台?

    假设集群有3台,允许1台挂掉(1 < 3/2+1);如果安装4台,同样只允许1台挂掉,多花了1台服务器却没有提高容错能力。所以奇数台更划算。

    生产经验参考:10台服务器装3台ZK,20台装5台,100台以上装11台。


    三、数据结构

    ZooKeeper的数据模型与Unix文件系统非常类似,整体可以看作是一棵树,每个节点称为一个ZNode。

    /
    ├── znode1
    │ ├── znode1/leaf1
    │ └── znode1/leaf2
    └── znode2
    └── znode2/leaf

    ZNode的特点:

    • 每个ZNode默认能够存储1MB的数据
    • 每个ZNode都通过其路径唯一标识,如/znode1/leaf1
    • 每次写操作都有唯一的事务ID(zxid)

    四、应用场景

    Zookeeper在分布式系统中的应用非常广泛,主要有以下几类:

    4.1 统一命名服务

    在分布式环境下,对应用/服务进行统一命名,便于识别。

    类比:IP地址不容易记住,但域名容易记住。可以将域名和IP的映射关系存储在Zookeeper中,客户端访问域名,Zookeeper返回对应的IP。

    4.2 统一配置管理

    分布式环境下配置文件同步非常常见,比如Kafka集群中所有节点的配置信息需要保持一致。

    实现方式:

  • 将配置信息写入Zookeeper的某个ZNode
  • 各客户端服务器监听该ZNode
  • 一旦ZNode中的数据被修改,Zookeeper立即通知所有监听的客户端
  • 4.3 统一集群管理

    实时掌握每个节点的状态:

  • 将节点信息写入Zookeeper上的一个ZNode
  • 监听该ZNode获取节点实时状态变化
  • 4.4 服务器动态上下线

    客户端能实时感知服务器的上下线变化,这也是Zookeeper最经典的应用场景之一,后面会有代码实现。

    4.5 软负载均衡

    在Zookeeper中记录每台服务器的访问数,让访问数最少的服务器去处理最新的客户端请求,实现动态负载均衡。


    五、安装与配置

    5.1 本地单机安装

    安装步骤:

    # 解压
    tar -zxvf apache-zookeeper-3.5.7-bin.tar.gz -C /opt/module/

    # 改名
    mv apache-zookeeper-3.5.7-bin/ zookeeper-3.5.7

    # 将zoo_sample.cfg改为zoo.cfg
    mv zoo_sample.cfg zoo.cfg

    # 修改dataDir路径(不要用默认的/tmp,容易被Linux清除)
    vim zoo.cfg
    # 修改为:dataDir=/opt/module/zookeeper-3.5.7/zkData

    # 创建zkData目录
    mkdir zkData

    基本操作:

    # 启动
    bin/zkServer.sh start

    # 查看状态
    bin/zkServer.sh status

    # 启动客户端
    bin/zkCli.sh

    # 退出客户端
    quit

    # 停止
    bin/zkServer.sh stop

    启动后用jps查看进程,能看到QuorumPeerMain说明Zookeeper已启动。

    5.2 配置参数解读(zoo.cfg)

    参数默认值说明
    tickTime 2000 通信心跳时间(毫秒),客户端与服务器的心跳间隔
    initLimit 10 Leader和Follower初始连接时能容忍的最多心跳数
    syncLimit 5 Leader和Follower通信超时的最大心跳数,超过则认为Follower死掉
    dataDir 数据存储目录,不要用默认的/tmp
    clientPort 2181 客户端连接端口,通常不修改

    initLimit和syncLimit的实际时间都是心跳数乘以tickTime。例如syncLimit=5,tickTime=2000,则超时时间为10秒。

    5.3 集群安装

    集群规划(以3台为例):

    主机名IPmyid
    hadoop102 192.168.10.102 2
    hadoop103 192.168.10.103 3
    hadoop104 192.168.10.104 4

    配置步骤:

    # 1. 在zkData下创建myid文件,写入对应编号
    echo 2 > /opt/module/zookeeper-3.5.7/zkData/myid
    # hadoop103写3,hadoop104写4

    # 2. 配置zoo.cfg,增加集群配置
    vim zoo.cfg

    zoo.cfg增加内容:

    dataDir=/opt/module/zookeeper-3.5.7/zkData

    #######################cluster##########################
    server.2=hadoop102:2888:3888
    server.3=hadoop103:2888:3888
    server.4=hadoop104:2888:3888

    参数解读:server.A=B:C:D

    • A:服务器编号,与myid对应
    • B:服务器地址
    • C:Follower与Leader交换信息的端口(2888)
    • D:Leader选举时服务器相互通信的端口(3888)

    # 3. 同步配置到其他机器
    xsync zoo.cfg

    # 4. 分别在三台机器上启动
    bin/zkServer.sh start

    # 5. 查看各节点状态
    bin/zkServer.sh status
    # hadoop102: follower
    # hadoop103: leader
    # hadoop104: follower

    5.4 集群启停脚本

    每次手动逐台启停比较麻烦,可以写一个脚本统一管理:

    #!/bin/bash
    case $1 in
    "start"){
    for i in hadoop102 hadoop103 hadoop104
    do
    echo "———- zookeeper $i 启动 ————"
    ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh start"
    done
    };;
    "stop"){
    for i in hadoop102 hadoop103 hadoop104
    do
    echo "———- zookeeper $i 停止 ————"
    ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh stop"
    done
    };;
    "status"){
    for i in hadoop102 hadoop103 hadoop104
    do
    echo "———- zookeeper $i 状态 ————"
    ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh status"
    done
    };;
    esac

    保存为zk.sh,赋权后使用:

    chmod u+x zk.sh
    zk.sh start # 启动集群
    zk.sh stop # 停止集群
    zk.sh status # 查看状态


    六、选举机制(面试重点)

    Zookeeper的选举机制分两种场景:第一次启动和非第一次启动。

    在理解选举之前,先记住三个关键概念:

    概念说明
    SID 服务器ID,与myid一致,集群内唯一
    ZXID 事务ID,标识一次状态变更,每次写操作递增
    Epoch Leader任期代号,每完成一轮投票该值增加

    6.1 第一次启动选举

    以5台服务器(myid分别为1-5)为例,按顺序启动:

    (1) 服务器1启动:发起一次选举,投自己1票。此时票数1票,不到半数(需要3票),状态保持LOOKING

    (2) 服务器2启动:发起选举,服务器1和2各投自己一票,然后交换选票信息。服务器1发现服务器2的myid比自己大,更改选票为服务器2。此时:服务器1有0票,服务器2有2票,还不到半数,1、2状态保持LOOKING

    (3) 服务器3启动:发起选举,服务器1和2都更改选票为服务器3。投票结果:服务器3有3票,超过半数,服务器3当选Leader。服务器1、2变为FOLLOWING,服务器3变为LEADING

    (4) 服务器4启动:此时服务器1、2、3已不是LOOKING状态,不会更改选票。服务器4服从多数,变为FOLLOWING

    (5) 服务器5启动:同服务器4,直接变为FOLLOWING

    总结规律(第一次启动):谁的myid大,谁当Leader(前提是票数过半)

    6.2 非第一次启动选举

    触发条件:

    • 服务器初始化启动
    • 服务器运行期间无法和Leader保持连接

    情况一:集群中已存在Leader
    机器只需与Leader建立连接并同步状态即可,不需要选举。

    情况二:集群中不存在Leader

    此时选举规则优先级(从高到低):

  • EPOCH大的直接胜出
  • EPOCH相同,ZXID大的胜出(ZXID大说明数据更新、数据更完整)
  • ZXID相同,SID大的胜出
  • 举例:5台服务器组成集群,SID为1、2、3、4、5,ZXID为8、8、8、7、7,SID=3的是Leader。某时刻3和5出现故障,开始选举:

    服务器EPOCHZXIDSID
    1 1 8 1
    2 1 8 2
    4 1 7 4

    按规则:EPOCH相同→比ZXID,服务器1和2的ZXID=8大于服务器4的ZXID=7→再比SID,服务器2的SID大于服务器1→服务器2当选新Leader


    七、客户端命令行操作

    7.1 常用命令汇总

    # 连接集群
    bin/zkCli.sh -server hadoop102:2181

    # 显示所有操作命令
    help

    # 查看节点内容
    ls /
    ls -s / # 附加详细信息

    # 查看节点数据
    get /path
    get -s /path # 附加统计信息
    get -w /path # 监听节点内容变化

    # 创建节点
    create /path "data" # 普通永久节点
    create -s /path "data" # 带序号的永久节点
    create -e /path "data" # 临时节点
    create -e -s /path "data" # 带序号的临时节点

    # 修改节点值
    set /path "newdata"

    # 查看节点状态
    stat /path

    # 删除节点
    delete /path # 删除单个节点(有子节点时失败)
    deleteall /path # 递归删除节点及其所有子节点

    7.2 节点类型详解

    ZNode分为四种类型:

    类型持久/临时有序/无序说明
    Persistent 持久 无序 断开连接后节点依旧存在
    Persistent_Sequential 持久 有序 节点名自动追加递增序号
    Ephemeral 临时 无序 断开连接后节点自动删除
    Ephemeral_Sequential 临时 有序 临时节点+自动序号

    临时节点的典型应用:服务注册。服务器启动时创建临时节点注册自己,服务器宕机后与Zookeeper连接断开,临时节点自动删除,其他客户端通过监听感知到服务器下线。

    有序节点的典型应用:分布式锁。利用序号的全局唯一性和单调递增性来判断锁的持有顺序。

    7.3 节点详细数据字段

    使用get -s /path或ls -s /path可以查看节点的详细信息:

    字段说明
    czxid 创建节点的事务zxid
    ctime 节点被创建的时间(毫秒数,从1970年开始)
    mzxid 最后一次更新节点的事务zxid
    mtime 最后一次修改节点的时间
    pZxid 最后一次更新子节点的zxid
    cversion 子节点变化号(子节点被修改次数)
    dataVersion 数据变化号
    aclVersion 访问控制列表的变化号
    ephemeralOwner 临时节点的session id,非临时节点为0
    dataLength 数据长度
    numChildren 子节点数量

    7.4 监听器原理

    监听器是Zookeeper实现通知机制的核心,原理如下:

    客户端
    ├── Main线程
    │ └── 创建ZooKeeper客户端
    │ ├── connect线程 → 将监听事件注册到Zookeeper
    │ └── listener线程 → 接收Zookeeper的通知,调用process()

    Zookeeper服务端
    └── 注册监听器列表 → 监听到数据/路径变化 → 通知listener线程

    两种常用监听:

    # 监听节点数据变化(值改变时触发)
    get -w /path

    # 监听子节点增减变化(子节点增加或删除时触发)
    ls -w /path

    **注意:Zookeeper的监听是一次性的!**注册一次只能监听一次。如果需要持续监听,每次收到通知后需要重新注册。


    八、客户端向服务端写数据流程

    Zookeeper的写操作分两种情况:

    情况一:写请求发送给Leader

    Client → Leader → 广播给所有Follower → 收到半数以上ACK → 提交写操作 → 通知所有Follower → 返回ACK给Client

    情况二:写请求发送给Follower

    Client → Follower → 转发给Leader → Leader广播给所有Follower → 半数以上ACK → 提交 → Follower通知Client

    核心点:所有写操作最终都由Leader处理,Follower接到写请求会转发给Leader;只要半数以上节点写入成功,就返回成功。


    九、面试常见问题

    Q1:Zookeeper的选举机制是什么?

    第一次启动:myid大的胜出(前提是票数过半);
    非第一次启动:①EPOCH大的胜出 ②EPOCH相同ZXID大的胜出 ③都相同SID大的胜出

    Q2:生产集群应该安装多少台Zookeeper?

    安装奇数台:

    • 10台服务器 → 3台ZK
    • 20台服务器 → 5台ZK
    • 100台以上 → 11台ZK

    服务器数量多:好处是提高可靠性,坏处是提高通信延时。超过11台后收益递减。

    Q3:Zookeeper的Watch机制是什么?

    客户端注册监听关心的ZNode,当ZNode发生变化(数据改变/节点删除/子节点增减)时,Zookeeper通知客户端。监听是一次性的,触发一次后需要重新注册。

    Q4:Zookeeper的常用命令有哪些?

    ls、get、create、set、delete、deleteall、stat


    小结

    Zookeeper核心知识体系
    ├── 是什么:文件系统 + 通知机制,基于观察者模式的分布式协调服务
    ├── 数据结构:树形ZNode,每节点最多1MB,路径唯一标识
    ├── 集群特点:半数存活即可服务 → 安装奇数台
    ├── 选举机制(面试重点)
    │ ├── 第一次启动:myid大的胜出
    │ └── 非第一次启动:EPOCH → ZXID → SID 依次比较
    ├── 节点类型:持久/临时 × 有序/无序 = 4种
    ├── 监听机制:注册监听 → 数据变化 → 通知client → 需重新注册
    └── 写数据流程:最终都由Leader处理,半数以上写入即成功

    Zookeeper在大数据生态中是基础设施级别的组件,Kafka用它做集群协调(高版本Kafka已可脱离Zookeeper),HBase用它做Master选举和Region管理。真正理解了Zookeeper的工作机制,再看这些组件的原理会轻松很多。

    赞(0)
    未经允许不得转载:171主机测评 » Zookeeper入门到实战详解
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址