Zookeeper集群操作与客户端命令
2026/6/3 18:47:19 网站建设 项目流程

1. 集群操作

1.1 集群安装

1) 集群规划

在hadoop102、hadoop103和hadoop104三个节点上都部署Zookeeper。

思考:如果是10台服务器,需要部署多少台Zookeeper?

2) 解压安装

(1) 在hadoop102解压Zookeeper安装包到/opt/module/目录下

[atguigu@hadoop102 software]$tar-zxvfapache-zookeeper-3.5.7-bin.tar.gz-C/opt/module/

(2) 修改apache-zookeeper-3.5.7-bin名称为zookeeper-3.5.7

[atguigu@hadoop102 module]$mvapache-zookeeper-3.5.7-bin/ zookeeper-3.5.7
3) 配置服务器编号

(1) 在/opt/module/zookeeper-3.5.7/目录下创建zkData

[atguigu@hadoop102 zookeeper-3.5.7]$mkdirzkData

(2) 在/opt/module/zookeeper-3.5.7/zkData目录下创建一个myid的文件

[atguigu@hadoop102 zkData]$vimyid

在文件中添加与server对应的编号(注意:上下不要有空行,左右不要有空格)

2

注意:添加myid文件,一定要在Linux里面创建,在notepad++里面很可能乱码

(3) 拷贝配置好的zookeeper到其他机器上

[atguigu@hadoop102 module]$ xsync zookeeper-3.5.7

并分别在hadoop103、hadoop104上修改myid文件中内容为3、4

4) 配置zoo.cfg文件

(1) 重命名/opt/module/zookeeper-3.5.7/conf这个目录下的zoo_sample.cfg为zoo.cfg

[atguigu@hadoop102 conf]$mvzoo_sample.cfg zoo.cfg

(2) 打开zoo.cfg文件

[atguigu@hadoop102 conf]$vimzoo.cfg

修改数据存储路径配置,增加如下配置:

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

(3) 配置参数解读

server.A=B:C:D

  • A:是一个数字,表示这个是第几号服务器;集群模式下配置一个文件myid,这个文件在dataDir目录下,这个文件里面有一个数据就是A的值,Zookeeper启动时读取此文件,拿到里面的数据与zoo.cfg里面的配置信息比较从而判断到底是哪个server。
  • B:是这个服务器的地址;
  • C:是这个服务器Follower与集群中的Leader服务器交换信息的端口;
  • D:是万一集群中的Leader服务器挂了,需要一个端口来重新进行选举,选出一个新的Leader,而这个端口就是用来执行选举时服务器相互通信的端口。

(4) 同步zoo.cfg配置文件

[atguigu@hadoop102 conf]$ xsync zoo.cfg
5) 集群操作

(1) 分别启动Zookeeper

[atguigu@hadoop102 zookeeper-3.5.7]$ bin/zkServer.sh start[atguigu@hadoop103 zookeeper-3.5.7]$ bin/zkServer.sh start[atguigu@hadoop104 zookeeper-3.5.7]$ bin/zkServer.sh start

(2) 查看状态

[atguigu@hadoop102 zookeeper-3.5.7]# bin/zkServer.sh statusJMX enabled by default Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg Mode: follower[atguigu@hadoop103 zookeeper-3.5.7]# bin/zkServer.sh statusJMX enabled by default Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg Mode: leader[atguigu@hadoop104 zookeeper-3.5.7]# bin/zkServer.sh statusJMX enabled by default Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg Mode: follower

1.2 选举机制(面试重点)

Zookeeper选举机制——第一次启动

核心概念

  • SID:服务器ID。用来唯一标识一台ZooKeeper集群中的机器,每台机器不能重复,和myid一致。
  • ZXID:事务ID。ZXID是一个事务ID,用来标识一次服务器状态的变更。在某一时刻,集群中的每台机器的ZXID值不一定完全一致,这和ZooKeeper服务器对于客户端"更新请求"的处理逻辑有关。
  • Epoch:每个Leader任期的代号。没有Leader时同一轮投票过程中的逻辑时钟值是相同的。每投完一次票这个数据就会增加。

选举过程

(1) 服务器1启动,发起一次选举。服务器1投自己一票。此时服务器1票数一票,不够半数以上(3票),选举无法完成,服务器1状态保持为LOOKING;

(2) 服务器2启动,再发起一次选举。服务器1和2分别投自己一票并交换选票信息:此时服务器1发现服务器2的myid比自己目前投票推举的(服务器1)大,更改选票为推举服务器2。此时服务器1票数0票,服务器2票数2票,没有半数以上结果,选举无法完成,服务器1,2状态保持LOOKING;

(3) 服务器3启动,发起一次选举。此时服务器1和2都会更改选票为服务器3。此次投票结果:服务器1为0票,服务器2为0票,服务器3为3票。此时服务器3的票数已经超过半数,服务器3当选Leader。服务器1,2更改状态为FOLLOWING,服务器3更改状态为LEADING;

(4) 服务器4启动,发起一次选举。此时服务器1,2,3已经不是LOOKING状态,不会更改选票信息。交换选票信息结果:服务器3为3票,服务器4为1票。此时服务器4服从多数,更改选票信息为服务器3,并更改状态为FOLLOWING;

(5) 服务器5启动,同4一样当小弟。

Zookeeper选举机制——非第一次启动

(1) 当ZooKeeper集群中的一台服务器出现以下两种情况之一时,就会开始进入Leader选举:

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

(2) 而当一台机器进入Leader选举流程时,当前集群也可能会处于以下两种状态:

  • 集群中本来就已经存在一个Leader:对于第一种已经存在Leader的情况,机器试图去选举Leader时,会被告知当前服务器的Leader信息,对于该机器来说,仅仅需要和Leader机器建立连接,并进行状态同步即可。
  • 集群中确实不存在Leader:假设ZooKeeper由5台服务器组成,SID分别为1、2、3、4、5,ZXID分别为8、8、8、7、7,并且此时SID为3的服务器是Leader。某一时刻,3和5服务器出现故障,因此开始进行Leader选举。

选举Leader规则

比较规则:(EPOCH, ZXID, SID)

  1. EPOCH大的直接胜出
  2. EPOCH相同,事务id大的胜出
  3. 事务id相同,服务器id大的胜出

1.3 ZK集群启动停止脚本

  1. 在hadoop102的/home/atguigu/bin目录下创建脚本
[atguigu@hadoop102 bin]$vimzk.sh

在脚本中编写如下内容:

#!/bin/bashcase$1in"start"){foriinhadoop102 hadoop103 hadoop104doecho---------- zookeeper$i启动 ----------ssh$i"/opt/module/zookeeper-3.5.7/bin/zkServer.sh start"done};;"stop"){foriinhadoop102 hadoop103 hadoop104doecho---------- zookeeper$i停止 ----------ssh$i"/opt/module/zookeeper-3.5.7/bin/zkServer.sh stop"done};;"status"){foriinhadoop102 hadoop103 hadoop104doecho---------- zookeeper$i状态 ----------ssh$i"/opt/module/zookeeper-3.5.7/bin/zkServer.sh status"done};;esac
  1. 增加脚本执行权限
[atguigu@hadoop102 bin]$chmodu+x zk.sh
  1. Zookeeper集群启动脚本
[atguigu@hadoop102 module]$ zk.sh start
  1. Zookeeper集群停止脚本
[atguigu@hadoop102 module]$ zk.sh stop

2. 客户端命令行操作

2.1 命令行语法

命令基本语法功能描述
help显示所有操作命令
ls path使用ls命令来查看当前znode的子节点 [可监听]
ls -w path监听子节点变化
ls -s path附加次级信息
create path data普通创建
create -s path data含有序列
create -e path data临时(重启或者超时消失)
get path获得节点的值 [可监听]
get -w path监听节点内容变化
get -s path附加次级信息
set path data设置节点的具体值
stat path查看节点状态
delete path删除节点
deleteall path递归删除节点
  1. 启动客户端
[atguigu@hadoop102 zookeeper-3.5.7]$ bin/zkCli.sh-serverhadoop102:2181
  1. 显示所有操作命令
[zk:hadoop102:2181(CONNECTED)1]help

2.2 znode节点数据信息

  1. 查看当前znode中所包含的内容
[zk:hadoop102:2181(CONNECTED)0]ls/[zookeeper]
  1. 查看当前节点详细数据
[zk:hadoop102:2181(CONNECTED)5]ls-s/[zookeeper]cZxid=0x0 ctime=Thu Jan 01 08:00:00 CST1970mZxid=0x0 mtime=Thu Jan 01 08:00:00 CST1970pZxid=0x0 cversion=-1dataVersion=0aclVersion=0ephemeralOwner=0x0 dataLength=0numChildren=1

参数解读

参数说明
(1) czxid创建节点的事务zxid。每次修改ZooKeeper状态都会产生一个ZooKeeper事务ID。事务ID是ZooKeeper中所有修改总的次序。每次修改都有唯一的zxid,如果zxid1小于zxid2,那么zxid1在zxid2之前发生。
(2) ctimeznode被创建的毫秒数(从1970年开始)
(3) mzxidznode最后更新的事务zxid
(4) mtimeznode最后修改的毫秒数(从1970年开始)
(5) pZxidznode最后更新的子节点zxid
(6) cversionznode子节点变化号,znode子节点修改次数
(7) dataVersionznode数据变化号
(8) aclVersionznode访问控制列表的变化号
(9) ephemeralOwner如果是临时节点,这个是znode拥有者的session id。如果不是临时节点则是0。
(10) dataLengthznode的数据长度
(11) numChildrenznode子节点数量

2.3 节点类型(持久/短暂/有序号/无序号)

节点类型分类

  • 短暂(Ephemeral):客户端和服务器端断开连接后,创建的节点自己删除
  • 持久(Persistent):客户端和服务器端断开连接后,创建的节点不删除

说明:创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护。

四种节点类型

(1)持久化目录节点:客户端与Zookeeper断开连接后,该节点依旧存在

(2)持久化顺序编号目录节点:客户端与Zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号

(3)临时目录节点:客户端与Zookeeper断开连接后,该节点被删除

(4)临时顺序编号目录节点:客户端与Zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号

注意:在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序。

命令示例

  1. 分别创建2个普通节点(永久节点+不带序号)
[zk:localhost:2181(CONNECTED)3]create /sanguo"diaochan"Created /sanguo[zk:localhost:2181(CONNECTED)4]create /sanguo/shuguo"liubei"Created /sanguo/shuguo

注意:创建节点时,要赋值

  1. 获得节点的值
[zk:localhost:2181(CONNECTED)5]get-s/sanguo diaochan cZxid=0x100000003 ctime=Wed Aug2900:03:23 CST2018mZxid=0x100000003 mtime=Wed Aug2900:03:23 CST2018pZxid=0x100000004 cversion=1dataVersion=0aclVersion=0ephemeralOwner=0x0 dataLength=7numChildren=1
  1. 创建带序号的节点(永久节点+带序号)
[zk:localhost:2181(CONNECTED)1]create /sanguo/weiguo"caocao"Created /sanguo/weiguo[zk:localhost:2181(CONNECTED)2]create-s/sanguo/weiguo/zhangliao"zhangliao"Created /sanguo/weiguo/zhangliao0000000000[zk:localhost:2181(CONNECTED)3]create-s/sanguo/weiguo/zhangliao"zhangliao"Created /sanguo/weiguo/zhangliao0000000001[zk:localhost:2181(CONNECTED)4]create-s/sanguo/weiguo/xuchu"xuchu"Created /sanguo/weiguo/xuchu0000000002

如果原来没有序号节点,序号从0开始依次递增。如果原节点下已有2个节点,则再排序时从2开始,以此类推。

  1. 创建短暂节点(短暂节点+不带序号or带序号)
# 创建短暂的不带序号的节点[zk:localhost:2181(CONNECTED)7]create-e/sanguo/wuguo"zhouyu"Created /sanguo/wuguo# 创建短暂的带序号的节点[zk:localhost:2181(CONNECTED)2]create-e-s/sanguo/wuguo"zhouyu"Created /sanguo/wuguo0000000001# 在当前客户端是能查看到的[zk:localhost:2181(CONNECTED)3]ls/sanguo[wuguo, wuguo0000000001, shuguo]# 退出当前客户端然后再重启客户端[zk:localhost:2181(CONNECTED)12]quit# 再次查看根目录下短暂节点已经删除[zk:localhost:2181(CONNECTED)0]ls/sanguo[shuguo]
  1. 修改节点数据值
[zk:localhost:2181(CONNECTED)6]set/sanguo/weiguo"simayi"

2.4 监听器原理

客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、节点删除、子目录节点增加删除)时,ZooKeeper会通知客户端。监听机制保证ZooKeeper保存的任何的数据的任何改变都能快速的响应到监听了该节点的应用程序。

监听原理详解

  1. 首先要有一个main()线程
  2. 在main线程中创建Zookeeper客户端,这时就会创建两个线程,一个负责网络连接通信(connect),一个负责监听(listener)。
  3. 通过connect线程将注册的监听事件发送给Zookeeper。
  4. 在Zookeeper的注册监听器列表中将注册的监听事件添加到列表中。
  5. Zookeeper监听到有数据或路径变化,就会将这个消息发送给listener线程。
  6. listener线程内部调用了process()方法。

常见的监听

  1. 监听节点数据的变化:get path [watch]
  2. 监听子节点增减的变化:ls path [watch]

示例

  1. 节点的值变化监听
# 在hadoop104主机上注册监听/sanguo节点数据变化[zk:localhost:2181(CONNECTED)26]get-w/sanguo# 在hadoop103主机上修改/sanguo节点的数据[zk:localhost:2181(CONNECTED)1]set/sanguo"xisi"# 观察hadoop104主机收到数据变化的监听WATCHER:: WatchedEvent state:SyncConnected type:NodeDataChanged path:/sanguo

注意:在hadoop103再多次修改/sanguo的值,hadoop104上不会再收到监听。因为注册一次,只能监听一次。想再次监听,需要再次注册。

  1. 节点的子节点变化监听(路径变化)
# 在hadoop104主机上注册监听/sanguo节点的子节点变化[zk:localhost:2181(CONNECTED)1]ls-w/sanguo[shuguo, weiguo]# 在hadoop103主机/sanguo节点上创建子节点[zk:localhost:2181(CONNECTED)2]create /sanguo/jin"simayi"Created /sanguo/jin# 观察hadoop104主机收到子节点变化的监听WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/sanguo

注意:节点的路径变化,也是注册一次,生效一次。想多次生效,就需要多次注册。


2.5 节点删除与查看

  1. 删除节点
[zk:localhost:2181(CONNECTED)4]delete /sanguo/jin
  1. 递归删除节点
[zk:localhost:2181(CONNECTED)15]deleteall /sanguo/shuguo
  1. 查看节点状态
[zk:localhost:2181(CONNECTED)17]stat/sanguo cZxid=0x100000003 ctime=Wed Aug2900:03:23 CST2018mZxid=0x100000011 mtime=Wed Aug2900:21:23 CST2018pZxid=0x100000014 cversion=9dataVersion=1aclVersion=0ephemeralOwner=0x0 dataLength=4numChildren=1

3. 客户端API操作

前提:保证hadoop102、hadoop103、hadoop104服务器上Zookeeper集群服务端启动。

3.1 IDEA环境搭建

  1. 创建一个工程:zookeeper

  2. 添加pom文件

<dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>RELEASE</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.8.2</version></dependency><dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.5.7</version></dependency></dependencies>
  1. 拷贝log4j.properties文件到项目根目录

需要在项目的src/main/resources目录下创建log4j.properties文件,内容如下:

log4j.rootLogger=INFO, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c]-%m%n log4j.appender.logfile=org.apache.log4j.FileAppender log4j.appender.logfile.File=target/spring.log log4j.appender.logfile.layout=org.apache.log4j.PatternLayout log4j.appender.logfile.layout.ConversionPattern=%d %p [%c]-%m%n
  1. 创建包名:com.atguigu.zk

  2. 创建类名称:zkClient


3.2 创建ZooKeeper客户端

// 注意:逗号前后不能有空格privatestaticStringconnectString="hadoop102:2181,hadoop103:2181,hadoop104:2181";staticintsessionTimeout=2000;privateZooKeeperzkClient=null;@Beforepublicvoidinit()throwsException{zkClient=newZooKeeper(connectString,sessionTimeout,newWatcher(){@Overridepublicvoidprocess(WatchedEventwatchedEvent){// 收到事件通知后的回调函数(用户的业务逻辑)System.out.println(watchedEvent.getType()+"--"+watchedEvent.getPath());// 再次启动监听try{List<String>children=zkClient.getChildren("/",true);for(Stringchild:children){System.out.println(child);}}catch(Exceptione){e.printStackTrace();}}});}

3.3 创建子节点

// 创建子节点@Testpublicvoidcreate()throwsException{// 参数1:要创建的节点的路径;参数2:节点数据;参数3:节点权限;参数4:节点的类型StringnodeCreated=zkClient.create("/atguigu","shuaige".getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);}

测试:在hadoop102的zk客户端上查看创建节点情况

[zk:localhost:2181(CONNECTED)16]get-s/atguigu shuaige

3.4 获取子节点并监听节点变化

// 获取子节点@TestpublicvoidgetChildren()throwsException{List<String>children=zkClient.getChildren("/",true);for(Stringchild:children){System.out.println(child);}// 延时阻塞Thread.sleep(Long.MAX_VALUE);}

(1) 在IDEA控制台上看到如下节点:

zookeeper sanguo atguigu

(2) 在hadoop102的客户端上创建再创建一个节点/atguigu1,观察IDEA控制台

[zk:localhost:2181(CONNECTED)3]create /atguigu1"atguigu1"

(3) 在hadoop102的客户端上删除节点/atguigu1,观察IDEA控制台

[zk:localhost:2181(CONNECTED)4]delete /atguigu1

3.5 判断Znode是否存在

// 判断znode是否存在@Testpublicvoidexist()throwsException{Statstat=zkClient.exists("/atguigu",false);System.out.println(stat==null?"not exist":"exist");}

4. 客户端向服务端写数据流程

4.1 写入请求直接发送给Leader节点

流程:

  1. Client向Leader发送write请求
  2. Leader将数据写入本地,同时向Follower1发送write请求
  3. Follower1写入完成,向Leader发送ack
  4. Leader收到ack后,向Client发送ack(此时已完成半数写入)
  5. Leader继续向Follower2发送write请求
  6. Follower2写入完成,向Leader发送ack

4.2 写入请求发送给Follower节点

流程:

  1. Client向Follower1发送write请求
  2. Follower1将请求转发给Leader
  3. Leader向Follower1发送write请求(要求Follower1写入)
  4. Follower1写入完成,向Leader发送ack
  5. Leader向Client发送ack(通过Follower1转发)
  6. Leader继续向其他Follower同步数据

总结

主题核心内容
集群安装规划→解压→配置myid→配置zoo.cfg→同步→启动
选举机制第一次启动:myid大的胜出;非第一次:Epoch→ZXID→SID
命令行操作ls、create、get、set、delete、stat、watch监听
节点类型持久/短暂 × 有序号/无序号 = 4种组合
监听器注册一次监听一次,数据变化和子节点变化两种
API操作创建客户端、创建节点、获取子节点、判断存在
写数据流程直接写给Leader vs 写给Follower转发

下一篇预告:服务器动态上下线监听案例(需求分析、具体实现、测试)

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询