概念
zookeeper官网:https://zookeeper.apache.org/
大数据生态系统里的很多组件的命名都是某种动物或者昆虫,比如hadoop就是 🐘,hive就是🐝。zookeeper即动物园管理者,顾名思义就是管理大数据生态系统各组件的管理员,如下图所示:
zooKeeper致力于为分布式应用提供一个高性能、高可用,且具有严格顺序访问控制能力的分布式协调服务。
- 高性能zooKeeper将全量数据存储在内存中,并直接服务于客户端的所有非事务请求,尤其适用于以读为主的应用场景。
- 高可用zooKeeper一般以集群的方式对外提供服务,一般3 ~ 5台机器就可以组成一个可用的zookeeper集群了,每台机器都会在内存中维护当前的服务器状态,并且每台机器之间都相互保持着通信。只要集群中超过一半的机器都能够正常工作,那么整个集群就能够正常对外服务。
- 严格顺序访问对于来自客户端的每个更新请求,ZooKeeper都会分配一个全局唯一的递增编号,这个编号反映了所有事务操作的先后顺序。
应用场景
ZooKeeper是一个经典的分布式数据一致性解决方案,致力于为分布式应用提供一个高性能、高可用,且具有严格顺序访问控制能力的分布式协调存储服务。
- 注册中心
- 配置中心
- 集群管理
- 分布式锁
- 生成分布式唯一ID
- 维护配置信息zooKeeper、config、nacos都可以当做配置中心使用。分布式兴起,许多服务使用相同的配置文件,如果配置文件发送变化,运维上需要逐个修改服务的配置文件,繁琐。通常会将配置文件部署在一个集群上,提供服务,高效快速且可靠地完成配置项的更改等操作,并能够保证各配置项在每台服务器上的数据一致性。zookeeper就可以提供这样一种服务,其使用Zab这种一致性协议来保证一致性。现在有很多开源项目使用zookeeper来维护配置,比如在hbase中,客户端就是连接 一个zookeeper,获得必要的hbase集群的配置信息,然后才可以进一步操作。还有在开源的消息队列kafka中,也使用zookeeper来维护broker的信息。在alibaba开源的soa框架dubbo中也广泛的使用zookeeper管理一些配置来实现服务治理。
- 集群管理&注册中心一个集群有时会因为各种软硬件故障或者网络故障,出现某些服务器挂掉而被移除集群,而某些服务器加入到集群中的情况,zookeeper会将这些服务器加入/移出的情况 通知给集群中的其他正常工作的服务器,以及及时调整存储和计算等任务的分配和执行等。此外zookeeper还会对故障的服务器做出诊断并尝试修复。
- 分布式锁多台服务器上运行着同一种服务,要协调各服务的进度,有时候需要保证当某个服务在进行某个操作时,其他的服务都不能进行该操作,即对该操作进行加锁,如果当前机器挂掉后,释放锁并fail over 到其他的机器继续执行该服务。
- 生成分布式唯一ID单库单表型系统中,通常可以使用数据库字段自带的auto_increment属性来自动为每条记录生成一个唯一的ID。但是分库分表后,就无法在依靠数据库的 auto_increment属性来唯一标识一条记录了。此时我们就可以用zookeeper在分布式环境下生成全局唯一ID。做法如下:每次要生成一个新Id时,创建一个持久顺序节点,创建操作返回的节点序号,即为新Id,然后把比自己节点小的删除即可。
数据模型
zookeeper的数据节点可以视为树状结构(或者目录),树中的各节点被称为znode(即zookeeper node),类似Linux的文件系统,一个znode可以有多个子节点。zookeeper节点在结构上表现为树状;使用路径path来定位某个znode,比如/ns-1/itcast/mysql/schema1/table1,此处ns-1、itcast、mysql、schema1、table1分别是根节点、2级节点、3级节点以及4级节点;其中ns-1是itcast的父节点,itcast是ns-1的子节点,itcast是mysql的父节点,mysql是itcast的子节点,以此类推。
znode,兼具文件和目录两种特点。既像文件一样维护着数据、元信息、ACL、时间戳等数据结构,又像目录一样可以作为路径标识的一部分。
znode节点
- 节点的数据:即znode data(节点path, 节点data)的关系就像是java map中(key, value)的关系
- 节点的子节点children
- 节点的状态stat:用来描述当前节点的创建、修改记录,包括cZxid、ctime等
节点状态stat的属性:
在zookeeper shell中使用get命令查看指定路径节点的data、stat信息:
[zk: localhost:2181(CONNECTED) 7] get /ns-1/tenant
cZxid = 0x6a0000000a
ctime = Wed Mar 27 09:56:44 CST 2019
mZxid = 0x6a0000000a
mtime = Wed Mar 27 09:56:44 CST 2019
pZxid = 0x6a0000000e
cversion = 2
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 2
属性说明:
- cZxid:数据节点创建时的事务 ID ,增删改才有事务 ID
- ctime:数据节点创建时的时间
- mZxid:数据节点最后一次更新时的事务 ID
- mtime:数据节点最后一次更新时的时间
- pZxid:数据节点的子节点最后一次被修改时的事务 ID
- cversion:子节点的更改次数
- dataVersion:节点数据的更改次数
- aclVersion:节点的 ACL 的更改次数
- ephemeralOwner:如果节点是临时节点,则表示创建该节点的会话的SessionID;如果节点是持久节点,则该属性值为 0
- dataLength:数据内容的长度
- numChildren:数据节点当前的子节点个数
节点类型:
zookeeper中的节点有两种,分别为临时节点和永久节点。节点的类型在创建时即被确定,并且不能改变。
临时节点:该节点的生命周期依赖于创建它们的会话。一旦会话(Session)结束,临时节点将被自动删除,当然也可以手动删除。虽然每个临时的Znode都会绑定到一个客户端会话,但他们对所有的客户端还是可见的。另外,ZooKeeper的临时节点不允许拥有子节点。
持久化节点:该节点的生命周期不依赖于会话,并且只有在客户端显示执行删除操作的时候,他们才能被删除。
单机安装
zookeeper底层依赖于jdk,需要提前安装java环境
Windows直接下载,bin/zkServer.cmd启动
Linux使用zookeeper-3.4.10.tar.gz,上传并解压,bin/zkServer.sh启动
// 解压zookeeper
tar-xzvf zookeeper-3.4.10.tar.gz
// 为zookeeper准备配置文件
// 进入conf目录
cd /home/zookeeper/zookeeper-3.4.10/conf
// 复制配置文件
cp zoo_sample.cfg zoo.cfg
// zookeeper根目录下新建data目录
mkdir data
// vi 修改配置文件中的dataDir
vi zoo.cfg
// 此路径用于存储zookeeper中数据的内存快照、及事物日志文件 dataDir=/home/zookeeper/zookeeper-3.4.10/data
// 启动zookeeper
// 进入zookeeper的bin目录
cd /home/zookeeper/zookeeper-3.4.10/bin
// 启动zookeeper
./zkServer.sh start
//启动:zkServer.sh start
//停止:zkServer.sh stop
//查看状态:zkServer.sh status
// 进入Shell命令窗口
./zkCli.sh
常用Shell命令
新增节点
create [-s][-e] path data #其中-s为有序节点,-e临时节点,默认持久化节点#创建持久化节点并写入数据:
create /hadoop "123456"
get /hadoop
#创建持久化有序节点,此时创建的节点名为指定节点名 + 自增序号/a0000000000[zk: localhost:2181(CONNECTED)2] create -s /a "aaa"
Created /a0000000000
[zk: localhost:2181(CONNECTED)3] create -s /b "bbb"
Created /b0000000001
[zk: localhost:2181(CONNECTED)4] create -s /c "ccc"
Created /c0000000002
get /a0000000000 / get /a
#创建临时节点,临时节点会在会话过期后被删除[zk: localhost:2181(CONNECTED)5] create -e /tmp "tmp"
Created /tmp
#创建临时有序节点,临时节点会在会话过期后被删除[zk: localhost:2181(CONNECTED)6] create -s-e /aa 'aaa'
Created /aa0000000004
[zk: localhost:2181(CONNECTED)7] create -s-e /bb 'bbb'
Created /bb0000000005
[zk: localhost:2181(CONNECTED)8] create -s-e /cc 'ccc'
Created /cc0000000006
更新节点
#更新节点的命令是 set ,可以直接进行修改,如下:[zk: localhost:2181(CONNECTED)3]set /hadoop "345"
cZxid = 0x4
ctime = Thu Dec 1214:55:53 CST 2019
mZxid = 0x5
mtime = Thu Dec 1215:01:59 CST 2019
pZxid = 0x4
cversion =0
dataVersion =1
aclVersion =0
ephemeralOwner = 0x0
dataLength =3
numChildren =0#也可以基于版本号进行更改,此时类似于乐观锁机制,当你传入的数据版本号 (dataVersion) 和当前节点的数据版本号不符合时,zookeeper 会拒绝本次修改:[zk: localhost:2181(CONNECTED)10]set /hadoop "3456"1
version No is not valid : /hadoop
删除节点
#删除节点的语法如下:
delete path [version]#和更新节点数据一样,也可以传入版本号,当你传入的数据版本号 (dataVersion) 和当前节点的数据版本号不符合时,zookeeper 不会执行删除操作。[zk: localhost:2181(CONNECTED)36] delete /hadoop 0
version No is not valid : /hadoop #无效的版本号 [zk: localhost:2181(CONNECTED)37] delete /hadoop 1[zk: localhost:2181(CONNECTED)38]#要想删除某个节点及其所有后代节点,可以使用递归删除,命令为 rmr path
查看节点
get path
[zk: localhost:2181(CONNECTED)1] get /hadoop
123456
cZxid = 0x4
ctime = Thu Dec 1214:55:53 CST 2019
mZxid = 0x4
mtime = Thu Dec 1214:55:53 CST 2019
pZxid = 0x4
cversion =0
dataVersion =0
aclVersion =0
ephemeralOwner = 0x0
dataLength =6
numChildren =0
节点各个属性如下表。其中一个重要的概念是 Zxid(ZooKeeper Transaction Id),ZooKeeper 节点的每一次更改都具有唯一的 Zxid,如果 Zxid1 小于 Zxid2,则Zxid1 的更改发生在 Zxid2 更改之前。
状态属性说明cZxid数据节点创建时的事务 IDctime数据节点创建时的时间mZxid数据节点最后一次更新时的事务 IDmtime数据节点最后一次更新时的时间pZxid数据节点的子节点最后一次被修改时的事务 IDcversion子节点的更改次数dataVersion节点数据的更改次数aclVersion节点的 ACL 的更改次数ephemeralOwner如果节点是临时节点,则表示创建该节点的会话的SessionID;如果节点是持久节点,则该属性值为 0dataLength数据内容的长度numChildren数据节点当前的子节点个数
查看节点状态
#可以使用 stat 命令查看节点状态,它的返回值和 get 命令类似,但不会返回节点数据[zk: localhost:2181(CONNECTED)2]stat /hadoop
cZxid = 0x4
ctime = Thu Dec 1214:55:53 CST 2019
mZxid = 0x4
mtime = Thu Dec 1214:55:53 CST 2019
pZxid = 0x4
cversion =0
dataVersion =0
aclVersion =0
ephemeralOwner = 0x0
dataLength =6
numChildren =0
查看节点列表
#查看节点列表有 ls path 和 ls2 path 两个命令,后者是前者的增强,不仅可 以查看指定路径下的所有节点,还可以查看当前节点的信息[zk: localhost:2181(CONNECTED)0]ls /
[cluster, controller_epoch, brokers, storm, zookeeper, admin, ...][zk: localhost:2181(CONNECTED)1] ls2 /
[cluster, controller_epoch, brokers, storm, zookeeper, admin, ....]
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x130
cversion =19
dataVersion =0
aclVersion =0
ephemeralOwner = 0x0
dataLength =0
numChildren =11
监听器get path [watch]
#使用 get path [watch] 注册的监听器能够在节点内容发生改变的时候,向客户端发出通知。需要注意的是 zookeeper的触发器是一次性的 (One-time trigger),即触发一次后就会立即失效。#客户端1,监听/hadoop[zk: localhost:2181(CONNECTED)4] get /hadoop watch#客户端2修改/hadoop,节点值改变,监听到修改事件
WATCHER:: WatchedEvent state:SyncConnected type:NodeDataChanged path:/hadoop
#客户端2[zk: localhost:2181(CONNECTED)5]set /hadoop 45678
监听器stat path [watch]
#使用 stat path [watch] 注册的监听器能够在节点状态发生改变的时候,向客户端发出通知#客户端1,监听/hadoop[zk: localhost:2181(CONNECTED)7]stat /hadoop watch#客户端2修改/hadoop,节点值改变,监听到修改事件
WATCHER:: WatchedEvent state:SyncConnected type:NodeDataChanged path:/hadoop #节点值改变#客户端2[zk: localhost:2181(CONNECTED)8]set /hadoop 112233
监听器ls\ls2 path [watch]
#使用 ls path [watch] 或 ls2 path [watch] 注册的监听器能够监听该节点下 所有子节点的增加和删除操作。[zk: localhost:2181(CONNECTED)9]ls /hadoop
watch[][zk: localhost:2181(CONNECTED)10] create /hadoop/yarn "aaa"
WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/hadoop
acl权限控制
zookeeper 类似文件系统,client 可以创建节点、更新节点、删除节点,那么如何做到节点的权限的控制呢?zookeeper的access control list 访问控制列表可以做到这一点。
acl 权限控制,使用scheme:id:permission 来标识,主要涵盖 3 个方面:
- 权限模式(scheme):授权的策略
- 授权对象(id):授权的对象
- 权限(permission):授予的权限
其特性如下:
- zooKeeper的权限控制是基于每个znode节点的,需要对每个节点设置权限
- 每个znode支持设置多种权限控制方案和多个权限
- 子节点不会继承父节点的权限,客户端无权访问某节点,但可能可以访问它的子节点
例如:
setAcl /test2 ip:192.168.60.130:crwda
// 将节点权限设置为Ip:192.168.60.130的客户端可以对节点进行增、删、改、查、管理权限
权限模式
采用何种方式授权
方案描述world只有一个用户:anyone,代表登录zookeeper所有人(默认)ip对客户端使用IP地址认证auth使用已添加认证的用户认证digest使用“用户名:密码”方式认证,密文
授权对象
给谁授予权限
授权对象ID是指,权限赋予的实体,例如:IP 地址或用户。
授予权限
授予什么权限
create、delete、read、writer、admin也就是 增、删、改、查、管理权限
这5种权限简写为cdrwa,注意:这5种权限中,delete是指对子节点的删除权限,其它4种权限指对自身节点的操作权限
权限ACL简写描述createc可以创建子节点deleted可以删除子节点(仅下一级节点)readr可以读取节点数据及显示子节点列表writew可以设置节点数据admina可以设置节点访问控制列表权限
授权的相关命令
命令使用方式描述getAclgetAcl
读取ACL权限setAclsetAcl
设置ACL权限addauthaddauth添加认证用户
案例:
- world授权模式
#命令setAcl <path> world:anyone:<acl>#例子[zk: localhost:2181(CONNECTED)1] create /node1 "node1" Created /node1 #查看权限[zk: localhost:2181(CONNECTED)2] getAcl /node1 'world,'anyone #world方式对所有用户进行授权 : cdrwa #具有增、删、改、查、管理 #world方式对所有用户进行授权 #增、删、改、查、管理 [zk: localhost:2181(CONNECTED)3] setAcl /node1 world:anyone:cdrwacZxid = 0x2 ctime = Fri Dec 1322:25:24 CST 2019 mZxid = 0x2 mtime = Fri Dec 1322:25:24 CST 2019 pZxid = 0x2 cversion =0 dataVersion =0 aclVersion =1 ephemeralOwner = 0x0 dataLength =5 numChildren =0
- IP授权模式
#命令setAcl <path> ip:<ip>:<acl>注意:远程登录zookeeper命令:./zkCli.sh -serverip#例子[zk: localhost:2181(CONNECTED)18] create /node2 "node2" Created /node2 #设置权限[zk: localhost:2181(CONNECTED)23] setAcl /node2 ip:192.168.60.129:cdrwa cZxid = 0xe ctime = Fri Dec 1322:30:29 CST 2019 mZxid = 0x10 mtime = Fri Dec 1322:33:36 CST 2019 pZxid = 0xe cversion =0 dataVersion =2 aclVersion =1 ephemeralOwner = 0x0 dataLength =20 numChildren =0[zk: localhost:2181(CONNECTED)25] getAcl /node2 'ip,'192.168.60.129 :cdrwa #使用IP非192.168.60.129 的机器 [zk: localhost:2181(CONNECTED)0] get /node2 Authentication is not valid : /node2 #没有权限#设置多个ip对同一个node的权限setAcl /node2 ip:192.168.60.129:cdrwa,ip:192.168.60.130:cdrwa
- Auth授权模式
#命令addauth digest <user>:<password>#添加认证用户 setAcl <path> auth:<user>:<acl>#例子[zk: localhost:2181(CONNECTED)2] create /node3 "node3" Created /node3 #添加认证用户 [zk: localhost:2181(CONNECTED)4] addauth digest itcast:123456 [zk: localhost:2181(CONNECTED)1] setAcl /node3 auth:itcast:cdrwa cZxid = 0x15 ctime = Fri Dec 1322:41:04 CST 2019 mZxid = 0x15 mtime = Fri Dec 1322:41:04 CST 2019 pZxid = 0x15 cversion =0 dataVersion =0 aclVersion =1 ephemeralOwner = 0x0 dataLength =5 numChildren =0[zk: localhost:2181(CONNECTED)0] getAcl /node3 'digest,'itcast:673OfZhUE8JEFMcu0l64qI8e5ek=: cdrwa #添加认证用户后可以访问 [zk: localhost:2181(CONNECTED)3] get /node3 node3cZxid = 0x15 ctime = Fri Dec 1322:41:04 CST 2019 mZxid = 0x15mtime = Fri Dec 1322:41:04 CST 2019 pZxid = 0x15cversion =0 dataVersion =0 aclVersion =1 ephemeralOwner = 0x0 dataLength =5numChildren =0
- Digest授权模式dai j s
#命令setAcl <path> digest:<user>:<password>:<acl>#这里的密码是经过SHA1及BASE64处理的密文,在SHELL中可以通过以下命令计算:echo-n<user>:<password>| openssl dgst -binary-sha1| openssl base64#先来计算一个密文echo-n itheima:123456 | openssl dgst -binary-sha1| openssl base64qlzQzCLKhBROghkooLvb+Mlwv4A=#例子[zk: localhost:2181(CONNECTED)4] create /node4 "node4" Created /node4 #使用是上面算好的密文密码添加权限: [zk: localhost:2181(CONNECTED)5] setAcl /node4 digest:itheima:qlzQzCLKhBROghkooLvb+Mlwv4A=:cdrwa cZxid = 0x1c ctime = Fri Dec 1322:52:21 CST 2019 mZxid = 0x1c mtime = Fri Dec 1322:52:21 CST 2019 pZxid = 0x1ccversion =0 dataVersion =0 aclVersion =1 ephemeralOwner = 0x0 dataLength =5numChildren =0[zk: localhost:2181(CONNECTED)6] getAcl /node4 'digest,'itheima:qlzQzCLKhBROghkooLvb+Mlwv4A=: cdrwa [zk: localhost:2181(CONNECTED)3] get /node4 Authentication is not valid : /node4 #没有权限 [zk: localhost:2181(CONNECTED)4] addauth digest itheima:123456 #添加认证用户[zk: localhost:2181(CONNECTED)5] get /node41#成功读取数据cZxid = 0x1c ctime = Fri Dec 1322:52:21 CST 2019 mZxid = 0x1c mtime = Fri Dec 1322:52:21 CST 2019 pZxid = 0x1c cversion =0 dataVersion =0 aclVersion =1 ephemeralOwner = 0x0dataLength =5numChildren =0
- 多种模式授权同一个节点可以同时使用多种模式授权
[zk: localhost:2181(CONNECTED)0] create /node5 "node5" Created /node5 #添加认证用户[zk: localhost:2181(CONNECTED)1] addauth digest itcast:123456 #多种模式授权[zk: localhost:2181(CONNECTED)2] setAcl /node5 ip:192.168.60.129:cdra,auth:itcast:cdrwa,digest:itheima:qlzQzCLKhBROgh kooLvb+Mlwv4A=:cdrwa
acl超级管理员
zookeeper的权限管理模式有一种叫做super,该模式提供一个超管可以方便的访问任何权限的节点
假设这个超管是:super:admin,需要先为超管生成密码的密文
#linuxecho-n super:admin | openssl dgst -binary-sha1| openssl base64
那么打开zookeeper目录下的/bin/zkServer.sh服务器脚本文件,找到如下一行:
nohup$JAVA"-Dzookeeper.log.dir=${ZOO_LOG_DIR}""-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}"
这就是脚本中启动zookeeper的命令,默认只有以上两个配置项,我们需要加一个 超管的配置项
"-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBv st5y6rkB6HQs="
加完如下:
nohup$JAVA"-Dzookeeper.log.dir=${ZOO_LOG_DIR}""- Dzookeeper.root.logger=${ZOO_LOG4J_PROP}""- Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBv st5y6rkB6HQs="
/ -cp"$CLASSPATH"$JVMFLAGS$ZOOMAIN"$ZOOCFG">"$_ZOO_DAEMON_OUT"2>&1< /dev/null &
之后启动zookeeper,输入如下命令添加权限
addauth digest super:admin #添加认证用户
版权归原作者 wzq_55552 所有, 如有侵权,请联系我们删除。