这里学习Zookeeper的选举机制、节点类型、Stat结构体以及写数据流程。
Zookeeper适合安装在奇数台服务器上,集群中半数以上的机器存活,则集群可用。故,又称之为半数机制。
Zookeeper虽然在配置文件中并没有指定Master和Slave,但是Zookeeper集群工作时是有一个节点为leader,其他为follower。leader是通过内部的选举机制临时产生的。
假设有五台服务器组成的Zookeeper集群,它们的id是1-5,同时它们都是最新启动的,也就是没有历史数据(在存放数据量这一点上,它们都是一样的)。如下图所示:
(1) 服务器1启动,此时只有它一台服务器启动了,它发出去的报文没有响应,所以它的选举机制一直是LOOKING状态(它投了自己一票)。
(2)服务器2启动,它与服务器1进行通信,互相交换自己的选举结果(服务器2投自己一票,服务器1投服务器2一票,此时服务器2两票,服务器1一票)。由于两者都没有历史数据,所以id值较大的服务器2胜出。但是由于没有达到超过半数以上故而leader未产生。
(3)服务器3启动,先投自己一票,然后与服务器1,2交换选举结果。由于服务器1 2均未产生leader,故而在服务器3启动时会投其一票。此时服务器3票数为3票,已经超过半数,故而晋级为leader。
(4)服务器4启动,此时已经有了leader,自动为follower(先入为主机制)。
(5)同服务器4一样,成功leader的小弟。
节点类型根据持久性分为持久性节点和临时性节点(短暂存活)。
持久性节点:客户端和服务端断开连接后,创建的节点不删除。
临时性节点:客户端和服务端断开连接后,创建的节点自己删除。
① 持久化目录节点
客户端与Zookeeper断开连接后,该节点依旧存在。
② 持久化顺序编号目录节点
客户端与Zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号。
说明:创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护。
在分布式系统中,顺序号可以被用于为所有的事件进行全局排序。这样客户端可以根据顺序号推断事件的顺序。
③ 临时目录节点
客户端与Zookeeper端口连接后,该节点被删除。
④ 临时顺序编号目录节点
客户端与Zookeeper端口连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号。
① 创建普通节点
//创建节点时必须同时包含数据
[zk: localhost:2181(CONNECTED) 9] create /jane1 love
Created /jane1
[zk: localhost:2181(CONNECTED) 10] ls /
[jane1, zookeeper]
② 创建短暂节点
[zk: localhost:2181(CONNECTED) 11] create -e /jane2 love
Created /jane2
当客户端端口连接后,该节点将不存在。如下当客户端端口连接后集群中其他Zookeeper监控情况:
[zk: localhost:2181(CONNECTED) 1] ls /
[jane1, jane2, zookeeper]
[zk: localhost:2181(CONNECTED) 2] ls /
[jane1, zookeeper]
③ 创建带序号的节点
[zk: localhost:2181(CONNECTED) 0] ls /
[jane1, zookeeper]
[zk: localhost:2181(CONNECTED) 1] create -s /jane2 loave
Created /jane20000000002
[zk: localhost:2181(CONNECTED) 4] create -s /jane1/jane11 love
Created /jane1/jane110000000000
如果路径下无节点,则序号从0开始。否则序号从节点数量开始。
④ 获取节点内容
[zk: localhost:2181(CONNECTED) 5] get /jane1
love
⑤ 修改节点数据
[zk: localhost:2181(CONNECTED) 8] set /jane1 "love me"
[zk: localhost:2181(CONNECTED) 9] get /jane1
love me
⑥ 集群环境下节点值变化监听
在server2中注册监听:
[zk: localhost:2181(CONNECTED) 4] get /jane1 watch
'get path [watch]' has been deprecated. Please use 'get [-s] [-w] path' instead.
love me
[zk: localhost:2181(CONNECTED) 5]
WATCHER::
在server1中修改/jane1
的值同时观察server2变化:
⑦ 监听节点的子节点变化(路径变化)
在server2注册路径监听:
[zk: localhost:2181(CONNECTED) 5] ls /jane1 watch
'ls path [watch]' has been deprecated. Please use 'ls [-w] path' instead.
[jan12, jane11, jane110000000000]
[zk: localhost:2181(CONNECTED) 6] ls -w /jane1
[jan12, jane11, jane110000000000]
在server1中为/jane1节点创建子节点同时观察server2变化:
可以发现监听只有一次有效。
⑧ 删除节点
delete /jane1/jane12
⑨ 递归删除节点
rmr /jane1/jane13
⑩ 查看节点状态
[zk: localhost:2181(CONNECTED) 23] stat /jane1
cZxid = 0x100000002
ctime = Sun Oct 06 15:36:15 CST 2019
mZxid = 0x10000000d
mtime = Sun Oct 06 15:55:45 CST 2019
pZxid = 0x100000011
cversion = 6
dataVersion = 3
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 4
节点结构如下所示:
[zk: localhost:2181(CONNECTED) 23] stat /jane1
cZxid = 0x100000002
ctime = Sun Oct 06 15:36:15 CST 2019
mZxid = 0x10000000d
mtime = Sun Oct 06 15:55:45 CST 2019
pZxid = 0x100000011
cversion = 6
dataVersion = 3
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 4
① cZxid
创建节点的事务zxid。每次修改Zookeeper状态都会收到一个zxid形式的时间戳,也就是Zookeeper事务ID。事务ID是Zookeeper中所有修改总的次序,每个修改都有唯一的zxid。如果zxid1小于zxid2,那么zxid1在zxid2之前发生。
② 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的数据长度。
(11) numChildren
znode子节点数量。
① 监听器原理详解
Zookeeper监听到有数据或者路径变化
,就会将这个消息发送给listener线程
。② 常见的监听器
get paht [watch]
get [-s] [-w] path
ls path [watch]
ls -w path