zookeeper基本使用
zookeeper基本使用
基本概念
通常情况下,单个物理节点很容易达到性能,计算或者容量的瓶颈,所以这个时候就需要多个物理节点来共同完成某项任务,一个分布式系统的本质是分布在不同网络或计算机上的程序组件,彼此通过信息传递来协同工作的系统,而Zookeeper正是一个分布式应用协调框架,在分布式系统架构中有广泛的应用场景。
官方文档解释:zookeeper它是一个分布式协调框架,是ApacheHadoop的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等
核心概念
一个基于内存,用于存储少量数据的数据库。核心概念:文件系统存储结构、监听通知机制
文件系统存储结构
Zookeeper维护一个了类似文件系统的数据结构,每个子目录项都被称作为znode (目录节点),和文件系统类似,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode。
zookeeper有以下几种类型的znode:
1、PERSISTENT持久化目录节点客户端与zookeeper断开连接后,该节点依旧存在,只要不手动删除该节点,他将永远存在
2、PERSISTENT_SEQUENTIAL持久化顺序编号目录节点客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号
3、EPHEMERAL临时目录节点客户端与zookeeper断开连接后,该节点被删除
4、EPHEMERAL_SEQUENTIAL临时顺序编号目录节点客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号
5、Container节点(3.5.3版本新增,如果Container节点下面没有子节点,则Container节点在未来会被Zookeeper自动清除,定时任务默认60s检查一次)
6、TTL节点(默认禁用,只能通过系统配置zookeeper.extendedTypesEnabled=true开启,不稳定
监听通知机制
客户端注册监听它关心的任意节点,或者目录节点及递归子目录节点。
1.如果注册的是对某个节点的监听,则当这个节点被删除,或者被修改时,对应的客户端将被通知。
2.如果注册的是对某个目录的监听,则当这个目录有子节点被创建,或者有子节点被删除,对应的客户端将被通知。
3.如果注册的是对某个目录的递归子节点进行监听,则当这个目录下面的任意子节点有目录结构的变化(有子节点被创建,或被删除)或者根节点有数据变化时,对应的客户端将被通知。
注意:所有的通知都是 一次性 的,及无论是对节点还是对目录进行的监听,一旦触发,对应的监听即被移除。递归子节点,监听是对所有子节点的,所以,每个子节点下面的事件同样只会被 触发一次。
应用场景
- 分布式配置中心
- 分布式注册中心
- 分布式锁
- 分布式队列
- 分布式屏障
- 集群选举
- 发布/订阅
安装
Step1:配置JAVA环境,并检查环境(建议JDK1.8)以上版本
java -version
Step2:下载并解压zookeeper
wget https://mirror.bit.edu.cn/apache/zookeeper/zookeeper‐3.5.8/apache‐zookeeper‐3.5.8‐bin.tar.gz # 此处若报错 XXXX use ‘--no-check-certificate’. 则在 wget后加入 --no-check-certificate 跳过证书检查 tar ‐zxvf apache‐zookeeper‐3.5.8‐bin.tar.gz cd apache‐zookeeper‐3.5.8‐bin
Step3:进入/conf目录下重命名zoo_sample.cfg配置文件
cp zoo_sample.cfg zoo.cfg
Step4:修改配置文件,将数据文件路径变更为自定义文件地址
dataDir=/opt/zookeeper/apache-zookeeper-3.5.8-bin/data
Step5:启动
// 可通过 bin/zkServer.sh 查看支持的参数 bin/zkServer.sh start conf/zoo.cfg
Step6:链接服务器
// 如果服务器与客户端在同一台机器,则可以省略ip和端口 bin/zkCli.sh -server 192.168.1.2:2181
如下图即表示zookeeper安装成功
基础命令
help :查看zookeeper所支持的所有命令
ZooKeeper -server host:port cmd args
addauth scheme auth
close
config [-c] [-w] [-s]
connect host:port
create [-s] [-e] [-c] [-t ttl] path [data] [acl]
delete [-v version] path
deleteall path
delquota [-n|-b] path
get [-s] [-w] path
getAcl [-s] path
history
listquota path
ls [-s] [-w] [-R] path
ls2 path [watch]
printwatches on|off
quit
reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
redo cmdno
removewatches path [-c|-d|-a] [-l]
rmr path
set [-s] [-v version] path data
setAcl [-s] [-v version] [-R] path acl
setquota -n|-b val path
stat [-w] path
sync path
注意:中括号为可选选项,否则为必填
create :创建新节点
create [-s] [-e] [-c] [-t ttl] path [data] [acl]
# -s:顺序结点
# -e:临时结点
# -c:容器结点
# -t:给结点添加过期时间,默认禁用
create /test-node some-data #没有添加任何参数,默认创建的是持久化结点
# 注意:
# 1.由于zookeeper是一结点组织数据的,没有相对路径,所以所有结点都是以 / 开头
# 2.临时结点下不允许创建子节点
# 3.容器结点当所有子节点都被删除时,下一次轮训会将容器结点清除
get :查看结点
get /test-node
set :修改结点
set /test-node update-data
stat :查看结点状态
stat /test-node
# 展示如下信息
[zk: localhost:2181(CONNECTED) 4] stat /test-node
// 创建znode的事务ID
cZxid = 0x9
// 创建时间
ctime = Fri Jan 28 12:11:58 CST 2022
// 最后修改znode的事务ID
mZxid = 0x9
// 最近修改时间
mtime = Fri Jan 28 12:11:58 CST 2022
// 最后添加或删除子节点的事务ID(子结点列表发生变化才会发生变化)
pZxid = 0x9
// znode的子节点结果集版本(子节点的变更会影响版本)
cversion = 0
// 数据的版本,当进行set时可以带上此版本号,若set之间版本号已经变更则set失败
dataVersion = 0
aclVersion = 0
// 如果是临时结点,所有者为sessionID,否则此字段为0
ephemeralOwner = 0x0
// 数据字段的长度(字节)
dataLength = 11
numChildren = 0
ls :查看子节点信息
#查看根目录下字节点
ls /
/**
[zk: localhost:2181(CONNECTED) 5] ls /
[test, test-node, zookeeper]
*/
#查看根目录下所有节点
ls -R /
/**
[zk: localhost:2181(CONNECTED) 6] ls -R /
/
/test
/test-node
/zookeeper
/test/sub0
/zookeeper/config
/zookeeper/quota
*/
事件监听机制
针对结点的监听,一定会触发事件,并且该事件立即被移除,所以事件监听是一次性的。
推送的信息不会将变更的数据一并推送,仅仅通知客户端有数据变更,变更的数据需要自己去获取。
// 注册监听的同时获取数据
get -w /path
// 注册监听的同时获取元数据信息
stat -w /path
# 效果展示
// 为 /test 结点注册监听
[zk: localhost:2181(CONNECTED) 30] get -w /test
xxx
//修改 /test 结点数据
[zk: localhost:2181(CONNECTED) 0] set /test xxx
// 服务端推送的变更信息
[zk: localhost:2181(CONNECTED) 31]
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/test
针对目录的监听,目录的变化会触发事件,且对应的监听也会被移除,后序结点的创建、删除不会再次触发监听事件。
注册目录监听,不会监听结点数据的变更,只会监听当前目录下结点数量的变更
// 为目录注册监听事件
ls -w /test
# 效果展示
// 注册监听事件
[zk: localhost:2181(CONNECTED) 31] ls -w /test
[]
// 新增子节点
[zk: localhost:2181(CONNECTED) 32] create /test/sub0
// 服务端推送内容
[zk: localhost:2181(CONNECTED) 33]
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/test
Created /test/sub0
Zookeeper的时间类型:
None:连接建立事件
NodeCreate:节点创建
NodeDeleted:节点删除
NodeDataChanged:节点数据变化
NodeChildrenChanged:子节点列表变化
DataWatchRemoved:结点监听被删除
ChildWatchRemoved:子节点监听被删除
ACL权限控制
Zookeeper的ACL权限控制可以控制节点的读写操作,保障数据的安全性,Zookeeper ACL权限设置分为三部分组成:权限模式(Scheme)、授权对象(ID)、权限信息(Permission)。最终组成 "scheme : id : permission" 格式的ACL请求信息。
Scheme(权限模式)
用来设置Zookeeper服务器进行权限验证的方式。
Zookeeper的权限验证方法大体分为一下类型:
- **范围验证:**zookeeper可以针对一个IP或者一段IP地址授予某种权限。例如:让一个IP地址为 "192.168.0.10" 的机器对服务器上某个节点具有写入的权限,或者通过 "192.168.0.1/32" 对一段IP地址的机器授。
- **口令验证:**即用户名密码方式。在Zookeeper中这种验证方式是 Digest 认证,而Digest这种任何智能方式受限在客户端传送 "username : password" 形式权限表示符后,Zookeeper 服务端会对密码部分使用 SHA-1 和 BASE64 算法进行加密。
- **Super:**一种特殊的 Digest 认证,具有Super权限的客户端可以对Zookeeper上的人已数据节点进行任意操作。
ID(授权对象)
授权对象就是我们需要把权限赋予哪一个对象。
对于4中不同的权限模式来说
- 采用IP方式,使用的权限对象可以是一个IP地址或一段IP地址;
- 采用Digest或Super方式,则对应于一个用户名;
- 采用World模式,是授权所有用户;
Permission(权限信息)
权限信息指可以在数据节点上执行的操作种类。
Zookeeper中已经定义好的权限有如下:
数据节点(c : create)创建权限:授予权限的对象可以在数据节点下创建子节点;
数据节点(w : wirte)更新权限:授予权限的对象可以更新改数据节点;
数据节点(r : read)读取权限:授予权限的对象可以读取该节点的内容以及子节点的列表信息;
数据节点(d : delete)删除权限:授予权限的对象可以删除该节点下的子节点;
数据节点(a : admin)管理员权限:授予权限的对象可以对该节点体进行ACL权限设置;
使用
// 获取某个节点的ACL权限信息
getAcl
// 设置某个节点的ACL权限信息
setAcl
// 输入认证授权信息,相当于注册用户信息; 注册时输入明文密码,zk将以密文形式存储
addauth
# 可以通过系统参数zookeeper.skipACL=yes进行配置,默认是no,可以配置为true,则配置过的ACL将不再进行权限检测
生成授权ID的方式
- 使用Zookeeper源码包内的类进行生成
@Test
public void generateSuperDigest() throws NoSuchAlgorithmException {
String sId = DigestAuthenticationProvider.generateDigest("yaien:test");
System.out.println(sId); //yaien:X/NSthOB0fD/OT6iilJ55WJVado=
}
- 在XShell生成
echo -n <username>:<password> | openssl dgst -binary -sha1 | openssl base64
// +7K83PhyQ3ijGj0ADmljf0quVwQ=
设置ACL的两种方式
- 节点创建的同时设置ACL
// 创建一个zknode节点并赋予 user1 用户读写的权限
create /zknode dddd digest:user1:+7K83PhyQ3ijGj0ADmljf0quVwQ=:rw
// 修改zknode节点的权限
setAcl /zknode digest:user1:+7K83PhyQ3ijGj0ADmljf0quVwQ=:acwrd
添加权限信息后的节点,不能直接访问,否则报错
[zk: localhost:2181(CONNECTED) 3] get /zknode
// 异常信息
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /zknode
访问前需要添加权限信息
// 添加访问权限信息
addauth digest user1:pass1
// 访问数据
get /zknode
[zk: localhost:2181(CONNECTED) 8] addauth digest user1:pass1
[zk: localhost:2181(CONNECTED) 9] get /zknode
dddd
[zk: localhost:2181(CONNECTED) 10]
- auth铭文授权
// 注册用户信息,后续可以直接使用铭文授权
addauth digest u100:p100
// 创建节点并赋予权限(这时u100用户授权信息会被zk保存,可以认为当前的授权用户为u100)
create /note-1 node1data auth:u100:p100:cawrd
// 访问数据
get /node-1
注意:创建时授予权限时,节点数据不能为空