Zookeeper安装和使用
安装
下载zk
官网下载地址: https://archive.apache.org/dist/zookeeper/
我们使用3.5.7的版本
# 上传文件到服务器
scp -r apache-zookeeper-3.5.7-bin.tar.gz root@服务器IP:/opt/software
tar -zxvf apache-zookeeper-3.5.7-bin.tar.gz
# 进行conf 目录
cp zoo_simple.cfg zoo.cfg
# 修改zk数据存放地址 默认地址在/tmp目录下 数据可能会被删除 不推荐使用
dataDir=apache-zookeeper-3.5.7-bin.tar.gz
下载jdk11
zk需要java环境 先安装jdk11
# 查看linux内核版本
arch
java11版本下载地址:https://www.oracle.com/java/technologies/downloads/#java11
可以使用镜像地址下载: https://mirrors.tuna.tsinghua.edu.cn/AdoptOpenJDK/11/jdk/x64/linux/
配置jdk环境
echo 'export PATH="/opt/software/jdk-11/bin:$PATH"' >> /etc/profile
source /etc/profile
启动zk
sh zkServer.sh start
jps查看进程是否启动, status查看zk为单机模式
启动客户端
zkCli.sh
# 退出客户端
quit
停止zk
sh zkServer.sh stop
配置文件参数
参数 | 说明 |
---|---|
tickTime = 2000 | 通信心跳时间,Zookeeper服务器与客户端心跳时间,单位毫秒 |
initLimit=10 | Leader和Follower初始连接时能容忍的最多心跳数(tickTime的数量) |
syncLimit=5 | Leader和Follower之间通信时间如果超过syncLimit * tickTime,Leader认为Follwer死 |
dataDir | 保存Zookeeper中的数据 注意:默认的tmp目录,容易被Linux系统定期删除,所以一般不用默认的tmp目录。 |
clientPort=2181 | 客户端连接端口,通常不做修改。 |
集群安装
- 在 zkData 目录下创建一个 myid 的文件
vi myid
-
在文件中添加与 server 对应的编号 2(注意:上下不要有空行,左右不要有空格)
-
在其他两天服务器上设置上修改 myid 文件中内容为 3、4
-
zoo.cfg增加集群配置
#######################cluster##########################
server.2=hadoop102:2888:3888
server.3=hadoop103:2888:3888
server.4=hadoop104:2888:3888
配置参数解读
server.A=B:C:D。
- A 是一个数字,表示这个是第几号服务器;
集群模式下配置一个文件 myid,这个文件在 dataDir 目录下,这个文件里面有一个数据就是 A 的值Zookeeper 启动时读取此文件,拿到里面的数据与 zoo.cfg 里面的配置信息比较从而判断到底是哪个 server
。 - B 是这个服务器的地址;
- C 是这个服务器 Follower 与集群中的 Leader 服务器交换信息的端口;
- D 是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的Leader,而这个端口就是用来执行选举时服务器相互通信的端口。
选举机制
第一次启动
-
服务器1启 动,发起一次选举。服务器1投自己一票。此时服务器1票数一票,不够半数以上(3票),选举无法完成,服务器1状态保持为LOOKING;
-
服务器2启动,再发起一次选举。服务器1和2分别投自己一票并交换选票信息:此时服务器1发现服务器2的myid比自己目前投票推举的(服务器1) 大,更改选票为推举服务器2。此时服务器1票数0票,服务器2票数2票,没有半数以上结果,选举无法完成,服务器1,2状态保持LOOKING
-
服务器3启动,发起一次选举。此时服务器1和2都会更改选票为服务器3。此次投票结果:服务器1为0票,服务器2为0票,服务器3为3票。此时服务器3的票数已经超过半数,服务器3当选Leader。服务器1,2更改状态为FOLLOWING,服务器3更改状态为LEADING;LOOKING LOOKING
-
服务器4启动,发起一次选举。此时服务器1,2,3已经不是LOOKING状态,不会更改选票信息。交换选票信息结果:服务器3为3票,服务器4为 1票。此时服务器4服从多数,更改选票信息为服务器3,并更改状态为FOLLOWING;
-
服务器5启动,同4一样当小弟。
非第一次启动
-
当ZooKeeper集群中的一台服务器出现以下两种情况之一时,就会开始进入Leader选举:
- 服务器初始化启动。
- 服务器运行期间无法和Leader保持连接。
-
而当一台机器进入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选举。
SID为1、2、4的机器投票情况:
-
服务器 | (EPOCH,ZXID,SID ) |
---|---|
1 | (1,8,1) |
2 | (1,8,2) |
4 | (1,7,4) |
选举Leader规则
:
- EPOCH大的直接胜出
- EPOCH相同,事务id大的胜出
- 事务id相同,服务器id大的胜出
所以应该是2号机器当选为Leader
命令行语法
命令基本语法 | 功能描述 |
---|---|
help | 显示所有操作命令 |
ls path | 使用 ls 命令来查看当前 znode 的子节点 -w 监听子节点变化 / -s 附加次级信息 |
create | 普通创建 -s 含有序列号 / -e 临时(重启或者超时消失) |
get path | 获得节点的值 -w 监听节点内容变化 / -s 附加次级信息 |
set | 设置节点的具体值 |
stat | 查看节点状态 |
delete | 删除节点 |
deleteall | 递归删除节点 |
# 启动客户端
sh zkCli.sh -server 服务器地址:2181
# 显示所有操作
help
# 查看当前znode中所包含的内容
ls /
# 查看当前节点详细数据
ls -s /
参数 | 说明 |
---|---|
czxid | 创建节点的事务 zxid |
ctime | znode 被创建的毫秒数(从 1970 年开始) |
mzxid | znode 最后更新的事务 zxid |
mtime | znode 最后修改的毫秒数(从 1970 年开始) |
pZxid | znode 最后更新的子节点 zxid |
cversion | znode 子节点变化号,znode 子节点修改次数 |
dataversion | znode 数据变化号 |
aclVersion | znode 访问控制列表的变化号 |
ephemeralOwner | 如果是临时节点,这个是 znode 拥有者的 session id。如果不是临时节点则是 0 |
dataLength | znode 的数据长度 |
numChildren | znode 子节点数量 |
节点类型
zk节点有4种类型:持久/短暂/有序号/无序号
持久(Persistent):客户端和服务器端断开连接后,创建的节点不删除
短暂(Ephemeral):客户端和服务器端断开连接后,创建的节点自己删除
- 持久化目录节点: 客户端与Zookeeper断开连接后,该节点依旧存在
- 持久化顺序编号目录节点: 客户端与Zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号
- 临时目录节点: 客户端与Zookeeper断开连接后,该节点被删除
- 临时顺序编号目录节点: 客户端与 Zookeeper 断开连接后 , 该节点被删除,只是Zookeeper给该节点名称进行顺序编号。
说明:创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护。注意:在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序
创建不带序号永久节点
create /city "beijing"
ls /
create /city/beijing "chaoyang"
# 获取节点的值
get -s /city
get -s /city/beijing
创建带序号的永久节点
[zk: localhost:2181(CONNECTED) 9] create -s /city/shenzheng "futian"
Created /city/shenzheng0000000001
如果原来没有序号节点,序号从 0 开始依次递增。如果原节点下已有 2 个节点,则再排序时从 2 开始,以此类推。
创建短暂节点
# 创建短暂的不带序号的节点
create -e /city/shanghai "qingpu"
# 创建短暂的带序号的节点
create -e -s /city/shanghai "qingpu"
退出当前客户端然后再重启客户端 查看根目录下短暂节点已经删除
修改节点数据值
set /city/shanghai "xiaoqing"
监听器Watch
客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、节点删除、子目录节点增加删除)时,ZooKeeper 会通知客户端。监听机制保证 ZooKeeper 保存的任何的数据的任何改变都能快速的响应到监听了该节点的应用程序。
原理
-
首先要有一个main()线程
-
在main线程中创建Zookeeper客户端,这时就会创建两个线程,一个负责网络连接通信(connet),一个负责监听(listener)。
-
通过connect线程将注册的监听事件发送给Zookeeper。
-
在Zookeeper的注册监听器列表中将注册的监听事件添加到列表中。
-
Zookeeper监听到有数据或路径变化,就会将这个消息发送给listener线程。
-
listener线程内部调用了process()方法。
监听类型
- 监听节点数据的变化
# 在集群主机001上 注册监听/city 节点数据变化
get -w /city
# 在集群主机002上修改/city 节点的数据
set /city "bj"
# 观察主机001收到的数据变化的监听
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged
path:/city
注意:在hadoop103再多次修改/sanguo的值,hadoop104上不会再收到监听。因为注册一次,只能监听一次。想再次监听,需要再次注册
。
- 监听子节点增减的变化
# 在 主机001上注册监听/city 节点的子节点变化
ls -w /city
# 在 主机002 /city 节点上创建子节点
create /city/hanghzou "hangzhou"
# 观察 主机001 收到子节点变化的监听
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged
path:/city
注意:节点的路径变化,也是注册一次,生效一次。想多次生效,就需要多次注册。
节点删除与查看
# 删除节点
delete /city/beijing
# 递归删除节点
deleteall /city/beijing
# 查看节点状态
stat /city