Zookeeper是一个开源的分布式的,为分布式框架提供协调服务的Apache项目。
Zookeeper从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper就将负责通知已经在Zookeeper上注册的那些观察者做出相应的反应。
1 ) Zookeeper:一个领导者 (Leader),多个跟随者 (Follower) 组成的集群;
2 ) 集群中只要有半数以上节点存活,Zookeeper集群就能正常服务。所以Zookeeper适合安装奇数台服务器;
3 ) 全局数据一致:每个Server保存一份相同的数据副本,Client无论连接到哪个Server,数据都是一致的。
4 ) 更新请求顺序执行,来自同一个Client的更新请求按其发送顺序依次执行。
5 ) 数据更新原子性,一次数据更新要么成功,要么失败
6 ) 实时性,在一定时间范围内,Client能读到最新数据
ZooKeeper数据模型的结构与Unix文件系统很类似,整体上可以看作是一棵树,每个节点称做一个ZNode。每一个ZNode默认能够存储1MB的数据,每个ZNode都可以通过其路径唯一标识。
提供的服务包括:统一命名服务、统一配置管理、统一集群管理、服务器节点动态上下线、软负载均衡等。
ZooKeeper有两种安装模式,最简单的方式是
最简单的方式是单机模式(standalone mode),它只需要在一台机器上面运行,
另一种方式是集群模式,集群模式需要多台服务器部署。
https://blog.csdn.net/m0_49683806/article/details/124626742
Zookeeper中的配置文件zoo.cfg中参数含义解读如下:
1)tickTime = 2000:通信心跳时间,Zookeeper服务器与客户端心跳时间,单位毫秒
2)initLimit = 10:LF初始通信时限
Leader和Follower初始连接时能容忍的最多心跳数(tickTime的数量)
3)syncLimit = 5:LF同步通信时限
Leader和Follower之间通信时间如果超过syncLimit * tickTime,Leader认为Follwer死掉,从服务器列表中删除Follwer。
4)dataDir:保存Zookeeper中的数据
注意:默认的tmp目录,容易被Linux系统定期删除,所以一般不用默认的tmp目录。
5)clientPort = 2181:客户端连接端口,通常不做修改。
SID:服务器ID。用来唯一标识一台ZooKeeper集群中的机器,每台机器不能重复,和myid一致。
ZXID:事务ID。ZXID是一个事务ID,用来标识一次服务器状态的变更。在某一时刻,集群中的每台机器的ZXID值不一定完全一致,这和ZooKeeper服务器对于客户端“更新请求”的处理逻辑有关。
Epoch:每个Leader任期的代号。没有Leader时同一轮投票过程中的逻辑时钟值是相同的。每投完一次票这个数据就会增加。
Zookeeper 选举机制分为两种情况:
第一次启动
(1) 服务器1启动,发起一次选举。服务器1投自己一票。此时服务器1票数一票,不够半数以上(3票),选举无法完成,服务器1状态保持为LOOKING;
(2) 服务器2启动,再发起一次选举。服务器1和2分别投自己一票并交换选票信息:此时服务器1发现服务器2的myid比自己目前投票推举的(服务器1)大,更改选票为推举服务器2。此时服务器1票数0票,服务器2票数2票,没有半数以上结果,选举无法完成,服务器1,2状态保持LOOKING;
(3) 服务器3启动,发起一次选举。此时服务器1和2都会更改选票为服务器3。此次投票结果:服务器1为0票,服务器2为0票,服务器3为3票。此时服各器3的票数已经超过半数,服务器3当选Leader。服务器1,2更改状态为FOLLOWING,服务器3更改状态为LEADING
(4) 服务器4启动,发起一次选举。此时服务器1,2,3已经不是LOOKING状态,不会更改选票信息。交换选票信息结果:服务器3为3票,服务器4为1票。此时服务器4服从多数,更改选票信息为服务器3,并更改状态为FOLLOWING:
(5) 服务器5启动,同4一样当小弟
非第一次启动
选举Leader规则:1. Epoch大的直接胜出;2. Epoch相同,事务id大的胜出。
命令基本语法 |
功能描述 |
help |
显示所有操作命令 |
ls path |
使用 ls 命令来查看当前znode的子节点 [可监听] -w 监听子节点变化 -s 附加次级信息 |
create |
普通创建 -s 含有序列 -e 临时(重启或者超时消失) |
get path |
获得节点的值 [可监听] -w 监听节点内容变化 -s 附加次级信息 |
set |
设置节点的具体值 |
stat |
查看节点状态 |
delete |
删除节点 |
deleteall |
递归删除节点 |
1)启动客户端
[atguigu@hadoop102 zookeeper-3.5.7]$ bin/zkCli.sh -server hadoop102:2181
2)显示所有操作命令
[zk: hadoop102:2181(CONNECTED) 1] help
1)查看当前znode中所包含的内容
[zk: hadoop102:2181(CONNECTED) 0] ls /
2)查看当前节点详细数据
[zk: hadoop102:2181(CONNECTED) 5] ls -s /
[zookeeper]
cZxid = 0x0 # 创建节点的事务zxid
# 每次修改ZooKeeper状态都会产生一个ZooKeeper事务ID。事务ID是ZooKeeper中所有修改总的次序。每次修改都有唯一的zxid,如果zxid1小于zxid2,那么zxid1在zxid2之前发生。
#######################################
ctime = Thu Jan 01 08:00:00 CST 1970 # znode被创建的毫秒数(从1970年开始)
mZxid = 0x0 # znode最后更新的事务zxid
mtime = Thu Jan 01 08:00:00 CST 1970 # znode最后修改的毫秒数(从1970年开始)
pZxid = 0x0 # znode最后更新的子节点zxid
cversion = -1 # znode子节点变化号,znode子节点修改次数
dataVersion = 0 # znode数据变化号
aclVersion = 0 # znode访问控制列表的变化号
ephemeralOwner = 0x0 # 如果是临时节点,这个是znode拥有者的session id。如果不是临时节点则是0。
dataLength = 0 # znode的数据长度
numChildren = 1 # znode子节点数量
1)分别创建2个普通节点(永久节点 + 不带序号)
[zk: localhost:2181(CONNECTED) 3] create /sanguo "diaochan"
Created /sanguo
[zk: localhost:2181(CONNECTED) 4] create /sanguo/shuguo "liubei"
Created /sanguo/shuguo
2)创建带序号的节点(永久节点+ 带序号)
#(1)先创建一个普通的根节点/sanguo/weiguo
[zk: localhost:2181(CONNECTED) 1] create /sanguo/weiguo "caocao"
Created /sanguo/weiguo
# (2)创建带序号的节点
[zk: localhost:2181(CONNECTED) 2] create -s /sanguo/weiguo/zhangliao "zhangliao"
Created /sanguo/weiguo/zhangliao0000000000
[zk: localhost:2181(CONNECTED) 3] create -s /sanguo/weiguo/zhangliao "zhangliao"
Created /sanguo/weiguo/zhangliao0000000001
[zk: localhost:2181(CONNECTED) 4] create -s /sanguo/weiguo/xuchu "xuchu"
Created /sanguo/weiguo/xuchu0000000002
3)创建短暂节点(短暂节点 + 不带序号or 带序号)
#(1)创建短暂的不带序号的节点
[zk: localhost:2181(CONNECTED) 7] create -e /sanguo/wuguo "zhouyu"
Created /sanguo/wuguo
#(2)创建短暂的带序号的节点
[zk: localhost:2181(CONNECTED) 2] create -e -s /sanguo/wuguo "zhouyu"
Created /sanguo/wuguo0000000001
#(3)在当前客户端是能查看到的
[zk: localhost:2181(CONNECTED) 3] ls /sanguo
[wuguo, wuguo0000000001, shuguo]
#(4)退出当前客户端然后再重启客户端
[zk: localhost:2181(CONNECTED) 12] quit
[atguigu@hadoop104 zookeeper-3.5.7]$ bin/zkCli.sh
#(5)再次查看根目录下短暂节点已经删除
[zk: localhost:2181(CONNECTED) 0] ls /sanguo
[shuguo]
4)修改节点数据值
[zk: localhost:2181(CONNECTED) 6] set /sanguo/weiguo "simayi"
客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、节点删除、子目录节点增加删除)时,ZooKeeper会通知客户端。监听机制保证ZooKeeper保存的任何的数据的任何改变都能快速的响应到监听了该节点的应用程序。
监听原理详解
1 ) 首先要有一个main()线程
2 ) 在main线程中创建Zookeeper客户端,这时就会创建两个线程,一个负责网络连接通信 (connet) ,一个负责监听 (listener)。
3 ) 通过connect线程将注册的监听事件发送给Zookeeper;
4 ) 在Zookeeper的注册监听器列表中将注册的监听事件添加到列表中;
5 ) Zookeeper监听到有数据或路径变化,就会将这个消息发送给listener线程;
6 ) listener线程内部调用了process()方法
常见的监听
1 ) 监听节点数据的变化 get path [watch]
2 ) 监听子节点增减的变化 ls path [watch]
节点的值变化监听
#(1)在hadoop104主机上注册监听/sanguo节点数据变化
[zk: localhost:2181(CONNECTED) 26] get -w /sanguo
#(2)在hadoop103主机上修改/sanguo节点的数据
[zk: localhost:2181(CONNECTED) 1] set /sanguo "xisi"
#(3)观察hadoop104主机收到数据变化的监听
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/sanguo
注意:在hadoop103再多次修改/sanguo的值,hadoop104上不会再收到监听。因为注册一次,只能监听一次。想再次监听,需要再次注册。
节点的子节点变化监听(路径变化)
#(1)在hadoop104主机上注册监听/sanguo节点的子节点变化
[zk: localhost:2181(CONNECTED) 1] ls -w /sanguo
[shuguo, weiguo]
#(2)在hadoop103主机/sanguo节点上创建子节点
[zk: localhost:2181(CONNECTED) 2] create /sanguo/jin"simayi"
Created /sanguo/jin
#(3)观察hadoop104主机收到子节点变化的监听
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/sanguo
注意:节点的路径变化,也是注册一次,生效一次。想多次生效,就需要多次注册。
#1)删除节点
[zk: localhost:2181(CONNECTED) 4] delete /sanguo/jin
#2)递归删除节点
[zk: localhost:2181(CONNECTED) 15] deleteall /sanguo/shuguo
#3)查看节点状态
[zk: localhost:2181(CONNECTED) 17] stat /sanguo
cZxid = 0x100000003
ctime = Wed Aug 29 00:03:23 CST 2018
mZxid = 0x100000011
mtime = Wed Aug 29 00:21:23 CST 2018
pZxid = 0x100000014
cversion = 9
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 1