Zookeeper的使用

时间:2024-10-29 06:59:36

1_客户端连接

通过bin目录下的zkCli.sh 命令连接即可

zkCli.sh

zkCli.sh默认连接的是当前节点的Zookeeper节点,如果我们要连接其他节点执行如下命令即可

zkCli.sh -timeout 5000 -server bobo02:2181

2_Zookeeper的数据结构

  1. 层次化的目录结构,命名符合常规文件系统规范
  2. 每个节点在 Z o o k e e p e r Zookeeper Zookeeper中叫做Znode,并且有一个唯一的路径标识
  3. 节点Znode可以包含数据和子节点(但是EPHEMERAL类型的节点不能有子节点)
  4. 客户端应用可以在节点上设置监听器

在这里插入图片描述


3_节点类型

1、znode有两种类型:

节点类型 说明
持久节点(Persistent 即使客户端断开连接,节点依然存在(断开连接不删除)。
临时节点(Ephemeral 客户端会话结束后,节点会被自动删除(断开连接自己删除)。
顺序节点(Sequential Z o o k e e p e r Zookeeper Zookeeper 会为该节点分配一个顺序号,节点名会以顺序号形式命名。
容器节点(Container 是一种特殊的持久性节点,用于管理一组相关的子节点。
当容器的最后一个子节点被删除时,该容器将被删除。

知道前两种类型即可,第三种和第四种节点类型是我的一个补充。


2、znode有四种形式的目录节点(默认是persistent)如下

序号 节点类型 描述
1 PERSISTENT 持久节点
2 PERSISTENT_SEQUENTIAL 持久有序节点
3 EPHEMERAL 短暂节点
4 EPHEMERAL_SEQUENTIAL 短暂有序节点

创建 Znode 时设置顺序标识,znode 名称后会附加一个值,顺序号是一个单调递增的计数器,有父节点维护在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序。

如果有多个Session创建同一个创建临时节点时让节点有序,则不会进行覆盖创建【Node already exists】,而是后面跟随一个递增的分布式序号(规避覆盖,分布式情况下统一命名)。

在这里插入图片描述


4_节点属性

一个 znode 节点不仅可以存储数据,还有一些其他特别的属性。

节点属性 注解
cZxid 该数据节点被创建时的事务Id
ctime 该数据节点创建时间
mZxid 该数据节点被修改时最新的事物Id
mtime 该数据节点最后修改时间
pZxid 当前节点的父级节点事务Id
cversion 子节点版本号(子节点修改次数,每修改一次值+1递增)
dataVersion 当前节点版本号(每修改一次值+1递增)
aclVersion 当前节点acl版本号(节点被修改acl权限,每修改一次值+1递增)
ephemeralOwner 临时节点标识,当前节点如果是临时节点,
则存储的创建者的会话id(sessionId),如果不是,那么值=0
dataLength 当前节点所存储的数据长度
numChildren 当前节点下子节点的个数
data 数据(通常小于 1 MB),二进制安全

Zxid保证事务的顺序一致性

Z o o K e e p e r ZooKeeper ZooKeeper在选举时通过比较各结点的zxid和机器ID选出新的主结点。

ZxidLeader节点生成,有新写入事件时,Leader生成新zxid并随提案一起广播,每个结点本地都保存了当前最近一次事务的 zxid,zxid 是递增的,所以谁的 zxid 越大,就表示谁的数据是最新的。

ZXID的生成规则如下:

在这里插入图片描述

ZXID 由两部分组成:

  • 任期(Epoch):完成本次选举后,直到下次选举前,由同一Leader负责协调写入;
  • 事务计数器:单调递增,每生效一次写入,计数器加一。

ZXID的高 32 位是 Epoch 用来标识朝代变化,比如每次选举 Epoch 都会加改变。

可以理解为当前集群所处的年代或者周期,每个 Leader 就像皇帝,都有自己的年号,所以每次改朝换代,Leader 变更之后,都会在前一个年代的基础上加 1。

这样就算旧的 Leader 崩溃恢复之后,也没有人听它的了。

ZXID的低 32 位是计数器,所以同一任期内,ZXID是连续的,每个结点又都保存着自身最新生效的ZXID,通过对比新提案的ZXID与自身最新ZXID是否相差“1”,来保证事务严格按照顺序生效的。


5_常用命令

推荐使用 help 查看命令使用,因为不同版本会有明显差异。

命令 描述 语法 示例
help 查看 Z o o k e e p e r Zookeeper Zookeeper 命令 help help
create 创建一个新节点。
-s 创建顺序节点,
-e 创建临时节点,
-c 创建容器节点,
-t 设置 TTL。
create [-s] [-e] [-c] [-t ttl] path [data] [acl] create -e /tmpNode "data" world:anyone:crwda
delete 删除指定路径节点,
(不能有子节点)
-v 指定版本号,
用于条件删除。
delete [-v version] path delete -v 1 /myNode
deleteall 递归删除指定节点及其所有子节点。 deleteall path deleteall /myNode
get 获取指定路径的节点数据。
-s 显示节点状态信息,
-w 添加监听器。
get [-s] [-w] path get -s /myNode
set 更新指定节点的数据。
-s 显示节点状态信息,
-v 指定版本号。
set [-s] [-v version] path data set -s -v 1 /myNode "newData"
ls 列出指定路径节点的子节点。
-s 显示节点状态信息,
-w 添加监听器,
-R 递归列出所有子节点。
ls [-s] [-w] [-R] path ls -s /myNode
stat 获取指定路径节点的统计信息。
(包括版本、修改时间等)
-w 添加监听器。
stat [-w] path stat -w /myNode
addWatch 添加永久性的监听器 addWatch [-m mode] path addWatch /myNode
[-m mode] 可选模式:[PERSISTENT, PERSISTENT_RECURSIVE]之一,
PERSISTENT不监听子节点,
RECURSIVE递归监听子节点,
默认使用递归策略。
addWatch -m PERSISTENT /myNode
removewatches 移除指定路径的监听器。
-c 移除子节点监听器,
-d 移除数据监听器,
-a 移除所有监听器,
-l 显示详细信息。
removewatches path [-c /-d /-a] [-l] removewatches /myNode -a -l
printwatches 设置是否打印监听器触发的事件,
on 开启,off 关闭。
printwatches on / off printwatches on
sync 确保指定路径的节点数据与所有 Zookeeper 服务器同步。 sync path sync /myNode
connect 连接到指定的 Zookeeper 服务器。 connect host:port connect localhost:2181
close 关闭当前会话,
但不退出 zkCli 工具。
close close
quit 退出 zkCli 工具。 quit quit
version 查看当前
Zookeeper 版本
version version
addauth 添加认证信息,
scheme 是认证方案(如 digest),
auth 是认证信息。
addauth scheme auth addauth digest user:password
whoami 查看当前使用者信息 whoami whoami
setAcl 设置指定节点的ACL
(访问控制列表)。
-s 显示统计信息,
-v 指定版本号,
-R 递归设置所有子节点的 ACL。
setAcl [-s] [-v version] [-R] path acl setAcl -R /myNode world:anyone:crwda
getAcl 获取指定路径节点的 ACL 信息,
-s 显示统计信息。
getAcl [-s] path getAcl -s /myNode
config 获取/设置 Zookeeper 配置信息。
-c 只输出版本和连接信息,
-w 用于添加监听器,
-s 用于显示详细信息。
config [-c] [-w] [-s] config -s
reconfig 动态修改 Zookeeper 集群配置。
-s 显示详细信息,
-v 指定版本号。
reconfig [-s] [-v version] [options] reconfig -s
[options] 可选操作,[-members]
[-add],[-remove],[-file path]
对节点动态变更配置的操作
getAllChildrenNumber 获取指定路径节点的所有子节点数量。 getAllChildrenNumber path getAllChildrenNumber /myNode
getEphemerals 获取指定路径下的所有临时节点。 getEphemerals path getEphemerals /myNode
history 显示命令历史记录。 history history
redo 重新执行之前的命令,
cmdno 是命令编号。
history配合使用
redo cmdno redo 1

注意事项

[ version ][watch] 是老版本的可选参数,目前使用[-v][-w]代替,ls2也被废弃,变为ls -s

以前的版本还有rmr命令,现在也被废弃了,仅支持deleteall

addWatch 是 3.6.x 以后支持的永久性的递归监视,这些监视在触发时不会删除,并且会以递归方式触发注册Znode以及所有子Znode的更改。

Z o o k e e p e r Zookeeper Zookeeper 的 ACL 包含读(r)、写(w)、创建(c)、删除(d)、管理员(a) 权限的设置。例如,world:anyone:cdrwa 表示所有用户均拥有创建、删除、读取和写入的权限。

reconfig 解决困扰已久的zk扩容,需要每台服务器都重新配置zoo.cfg文件和重启zk的问题,这个功能需要在配置文件中提前开启。


6_Session

Client和 Z o o k e e p e r Zookeeper Zookeeper 集群建立连接,整个session状态变化如图所示:

在这里插入图片描述

如果 Client 因为 Timeout Z o o k e e p e r Zookeeper Zookeeper Server 失去连接,client处在 CONNECTING 状态,会自动尝试再去连接Server,如果在 Session 有效期内再次成功连接到某个Server,则回到 CONNECTED 状态。

如果因为网络状态不好,Client和Server失去联系,client会停留在当前状态,会尝试主动再次连接 Z o o k e e p e r Zookeeper Zookeeper Server。

Client不能宣称自己的Session ExpiredSession Expired是由 Z o o k e e p e r Zookeeper Zookeeper Server来决定的,Client可以选择自己主动关闭Session

连接客户端的时候,会消耗一个事务id(简称Session也要消耗事务id即Zxid),断开连接也要统一所有节点所以还会消耗一个事务id。

Session会统一视图,所有节点一致,所以假设当前链接的节点当掉了,连到其他 follow 临时节点也不会消失。


7_Watcher事件监听

监听某个节点的数据内容变化,通过 get 命令 带 -w 参数即可,get path watch 实现监控的。

注意监听一次节点只会触发一次(3.6.x支持永久递归监视),如果要实现多次监听,那么可以在触发事件的处理函数中再次追加对节点的监听操作。

子节点的改变:

监听节点下面的子节点的改变。

[zk: localhost:2181(CONNECTED) 14] ls -w /app1
[]

Watcher监听机制的工作原理

Z o o k e e p e r Zookeeper Zookeeper 允许客户端向服务端的某个Znode注册一个Watcher监听,当服务端的一些指定事件触发了这个Watcher,服务端会向指定客户端发送一个事件通知来实现分布式的通知功能,然后客户端根据 Watcher通知状态和事件类型做出业务上的改变。

可以把Watcher理解成客户端注册在某个Znode上的触发器,当这个Znode节点发生变化时(增删改查),就会触发Znode对应的注册事件,注册的客户端就会收到异步通知,然后做出业务的改变。

在这里插入图片描述

  • Z o o K e e p e r ZooKeeper ZooKeeperWatcher 机制主要包括客户端线程、客户端 WatcherManager Z o o k e e p e r Zookeeper Zookeeper服务器三部分。
  • 客户端向 Z o o K e e p e r ZooKeeper ZooKeeper服务器注册 Watcher 的同时,会将 Watcher 对象存储在客户端的WatchManager中。
  • z o o k e e p e r zookeeper zookeeper服务器触发 watcher 事件后,会向客户端发送通知, 客户端线程从 WatcherManager 中取出对应的 Watcher 对象来执行回调逻辑。

Watcher 特性总结:

特性 说明
一次性 一个Watch事件是一个一次性的触发器。
一次性触发,客户端只会收到一次这样的信息。
异步 Z o o k e e p e r Zookeeper Zookeeper服务器发送watcher的通知事件到客户端是异步的,
不能期望能够监控到节点每次的变化,
Z o o k e e p e r Zookeeper Zookeeper只能保证最终的一致性,而无法保证强一致性。
轻量级 Watcher 通知非常简单,
它只是通知发生了事件,而不会传递事件对象内容。
客户端串行 执行客户端 Watcher 回调的过程是一个串行同步的过程。
注册 注册 watchergetDataexistsgetChildren方法
触发 触发 watchercreatedeletesetData方法