1.什么是zookeeper?
zookeeper是一个开源的分布式协调服务,由雅虎创建的,基于google chubby.是一个分布式数据一致性的解决方案
2.特性
顺序一致性:在一个客户端发起的事务请求(写请求),会严格按照请求顺序在zk中执行。
原子性:所有的事务请求在集群中的所有节点的处理结果是一致的,要么都成功,要么都失败。
可靠性:一旦服务器成功的处理了某个事务请求,并且对客户端做了响应,那么这个数据一定会存储在整个集群中,并保留下来。
实时性:一旦事务被成功应用,所有的客户端都会查到相应的数据(近实时)
3.数据模型
zk的数据节点类似于文件系统,是由数据节点组成的树形结构,每个节点都称为一个znode,可以存储数据以及节点的状态信息.znode是zk中的最小数据单元。
节点特性:
持久化节点(PERSISTENT):持久化节点一旦创建,就会一直存储在zk系统中,直到主动删除为止
持久化顺序节点(PERSISTENT_SEQUENTIAL):在创建顺序节点时,会在节点的名字后面加上一个序号。在同一个目录的顺序节点,会共同维护一个顺序,序号依次递增,序号范围[0,Integer.Max]
临时节点(EPHEMERAL):临时节点的生命周期和客户端的会话保持一致,当会话结束,节点自动被清理。临时节点下不能创建子节点
临时顺序节点(EPHEMERAL_SEQUENTIAL):比临时节点多了一个顺序性.
zkCli命令
create -s -e /path value acl -s顺序节点 -e 临时节点
delete /path [version] 删除节点 (有子节点不能删除)
rmr path 可以删除当前节点及子节点
get /path 获取节点信息
set /path data [version] 修改节点的值
ls /path 显示子节点
ls2 /path 显示版本信息及子节点
stat /path [watch]显示节点的版本信息
例如 stat /path true显示节点的版本信息
getAcl /path 获取节点权限
setAcl path acl 修改节点权限
addauth scheme auth 添加权限
watch
zk提供了分布式数据的发布和订阅功能,zk服务端允许客户端注册一个监听,当服务端数据变化时,服务器会生成一个事件通知给客户端,zk的监听是一次性的,既当触发一次通知后,当前watch就会失效,需要重新注册监听
ACL节点权限控制
zk为节点提供权限控制功能,以提高节点数据的安全性,避免误操作导致系统出现安全事故。
节点的权限类型
create、delete、read、write、admin既cdrwa 创建、删除、读、写、管理5种权限
以下信息摘自官网
CREATE: you can create a child node 可以创建子节点
DELETE: you can delete a child node 删除子节点
READ: you can get data from a node and list its children. 可以获取节点数据并查看子节点
WRITE: you can set data for a node 修改节点数据
ADMIN: you can set permissions 为节点设置权限
zk权限的方案schema
world:anyone 相当于没有权限,任何人都能访问(默认级别)
auth 不需要id控制,任何通过认证的用户都能访问
digest:username:password 通过用户名密码控制权限
ip:host 通过ip地址控制权限
world has a single id, anyone, that represents anyone.
auth doesn't use any id, represents any authenticated user.
digest uses a username:password string to generate MD5 hash which is then used as an ACL ID identity. Authentication is done by sending the username:password in clear text. When used in the ACL the expression will be the username:base64 encoded SHA1 password digest.
ip uses the client host IP as an ACL ID identity. The ACL expression is of the form addr/bits where the most significant bits of addr are matched against the most significant bits of the client host IP.
节点状态信息
get /node
aaaba 节点的数据
cZxid = 0x47 节点创建id(创建后不会改变)
ctime = Sat Jan 26 19:29:08 CST 2019 创建时间 (创建后不会改变)
mZxid = 0x52 节点修改的id(节点本身数据修改时改变)
mtime = Sat Jan 26 20:02:38 CST 2019 最后修改时间(节点本身数据修改时改变)
pZxid = 0x4e 子节点id (子节点的创建、删除改变)
cversion = 6 子节点版本 (子节点的创建、删除改变)
dataVersion = 4 数据版本 (节点本身数据修改时改变)
aclVersion = 0 acl版本
ephemeralOwner = 0x0 如果是临时节点存储会话id,非临时节点为0
dataLength = 5 数据长度
numChildren = 6 子节点数量
以下为测试数据
初始化 | 修改数据 | 创建子节点 | 修改子节点数据 | 创建孙子节点 | 创建第二个子节点 | 删除第二个子节点 |
cZxid = 0x54 | cZxid = 0x54 | cZxid = 0x54 | cZxid = 0x54 | cZxid = 0x54 | cZxid = 0x54 | cZxid = 0x54 |
ctime = Sat Jan 26 21:16:48 CST 2019 | ctime = Sat Jan 26 21:16:48 CST 2019 | ctime = Sat Jan 26 21:16:48 CST 2019 | ctime = Sat Jan 26 21:16:48 CST 2019 | ctime = Sat Jan 26 21:16:48 CST 2019 | ctime = Sat Jan 26 21:16:48 CST 2019 | ctime = Sat Jan 26 21:16:48 CST 2019 |
mZxid = 0x54 | mZxid = 0x57 | mZxid = 0x57 | mZxid = 0x57 | mZxid = 0x57 | mZxid = 0x57 | mZxid = 0x57 |
mtime = Sat Jan 26 21:16:48 CST 2019 | mtime = Sat Jan 26 21:18:27 CST 2019 | mtime = Sat Jan 26 21:18:27 CST 2019 | mtime = Sat Jan 26 21:18:27 CST 2019 | mtime = Sat Jan 26 21:18:27 CST 2019 | mtime = Sat Jan 26 21:18:27 CST 2019 | mtime = Sat Jan 26 21:18:27 CST 2019 |
pZxid = 0x54 | pZxid = 0x54 | pZxid = 0x58 | pZxid = 0x58 | pZxid = 0x58 | pZxid = 0x5b | pZxid = 0x5c |
cversion = 0 | cversion = 0 | cversion = 1 | cversion = 1 | cversion = 1 | cversion = 2 | cversion = 3 |
dataVersion = 0 | dataVersion = 1 | dataVersion = 1 | dataVersion = 1 | dataVersion = 1 | dataVersion = 1 | dataVersion = 1 |
dataLength = 3 | dataLength = 2 | dataLength = 2 | dataLength = 2 | dataLength = 2 | dataLength = 2 | dataLength = 2 |
numChildren = 0 | numChildren = 0 | numChildren = 1 | numChildren = 1 | numChildren = 1 | numChildren = 2 | numChildren = 1 |
集群的角色
leader
1.负责集群事物请求的处理
2.与follower和observer节点同步数据
3.负责发起事务请求的投票
follower节点
1.处理客户端的非事务请求并将事务请求转发到leader节点
2.参与事务请求处理的投票(客户端的一个事务请求,需要集群中的半数以上的节点投票通过后,才能通知leader commit;leader会发起一个提案,要求follower投票)
3.参与leader选举的投票
observer
1.将事务请求转发至leader节点
2.不参与事务请求的投票及leader选举的投票
observer的目的是为了扩展系统,提高读取速度。
zk的应用场景
1.统一配置管理
实现思路:zk采用push和pull相结合的方式,配置管理端push配置到zk服务端,应用节点在zk中注册自己关心节点的监听,当数据修改时,服务端就会向客户端推送watch事件通知,client收到通知后主动去zk pull更新的数据,并存储在本地,
满足以下条件时,适合使用统一配置中心
1.数据量较小
2.配置需要动态修改
3.集群中的各个机器共享配置
2.分布式锁
所有的服务节点尝试去zk创建一个相同的锁节点(临时节点),同一时刻只能有一个服务创建成功,创建成功的服务便获取到了锁,创建失败的服务去注册锁节点的监听,当锁节点被删除时,zk会将事件通知给服务节点,服务在获取到事件后,再去创建锁节点,创建成功的服务获取到锁。依次类推
3.master选举
与分布式锁的思路类似,服务尝试去注册相同的选举节点,注册成功的服务为master服务。
4.负载均衡
在zk中创建一个存储服务信息的根节点如/servers,在服务启动后在根节点下创建服务信息的子节点。
当客户端请求到达时,先获取当前服务器的列表信息,根据自定义的负载均衡算法,选取一个服务来处理客户端的请求。
5.ID生成器
在zk的指定节点下创建临时有序节点,根据节点的序号来做ID
6.分布式队列
- 通过getChildren获取指定根节点下的所有子节点,子节点就是任务
- 确定自己节点在子节点中的顺序
- 如果自己不是最小的子节点,那么监控比自己小的上一个子节点,否则处于等待
- 接收watcher通知,重复流程