3.ZooKeeper深度介绍

3.ZooKeeper进阶

3.1 Znode数据结构

在这里插入图片描述

  1. ZK有一个最开始的节点 /
  2. ZK的节点叫做znode节点
  3. 每个znode节点都可存储数据
  4. 每个znode节点(临时节点除外)都可创建自己的子节点
  5. 多个znode节点共同形成了znode树
  6. Znode树的维系是在内存中,目的是供用户快速的查询。定期会做持久化,保存磁盘上,数据更加安全。
  7. 每个znode节点都是一个路径(通过路径来定位这个节点)
  8. 每个路径名都是唯一的。

3.1.1 目录结构

层次的,目录型结构,便于管理逻辑关系
znode信息

  • 包含最大1MB的数据信息
  • 记录了zxid等元数据信息

3.1.2 节点类型

znode有两种类型,临时的(ephemeral)和持久的(persistent)
znode支持序列SEQUENTIAL
临时znode
客户端会话结束时,ZooKeeper将该临时znode删除,临时znode没有子节点
持久znode
不依赖于客户端会话,只有当客户端明确要删除该持久znode时才会被删除,znode的类型在创建时确定并且之后不能再修改
有序znode节点被分配唯一单调递增的整数。比如:客户端创建有序znode,路径为/task/task-,则ZooKeeper为其分配序号1,并追加到znode节点:/task/task-000000001。有序znode节点唯一,同时也可根据该序号查看znode创建顺序。
znode有四种形式的目录节点

  • PERSISTENT:普通持久
  • EPHEMERAL:普通临时
  • PERSISTENT_SEQUENTIAL:顺序持久
  • EPHEMERAL_SEQUENTIAL:顺序临时
    要想执行以下指令,需要先启动zk服务器端,再启动zk客户端
    ./zkServer.sh start:启动zk服务器端
    ./zkCli.sh:启动zk客户端

3.2 Zookeeper客户端命令行操作

在这里插入图片描述
启动三个节点上ZKServer,然后在某一个节点上启动一个客户端

#node2、node3、node4上同时执行命令
zkServer.sh start
#node2、node3、node4查看启动的状态
zkServer.sh status
#在node4上启动一个客户端
[root@node4 ~]# zkCli.sh

help显示所有的命令

[zk: localhost:2181(CONNECTED) 0] help
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

查看指定节点下的所有内容

[zk: localhost:2181(CONNECTED) 1] ls /
[zookeeper]

查看指定节点详细信息以及它的子节点

[zk: localhost:2181(CONNECTED) 2] ls2 /
'ls2' has been deprecated. Please use 'ls
[-s] path' instead.
[zookeeper]
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1
[zk: localhost:2181(CONNECTED) 3] ls -s /
[zookeeper] #表示 节点 /下的子节点
#以下信息为节点/的详细信息
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1

监听查看,创建节点

#node4
[zk: localhost:2181(CONNECTED) 4] ls -w /
[zookeeper]
#node3
[zk: localhost:2181(CONNECTED) 0] create
/wzyy "phone game"
Created /wzyy
#node4上的变化
[zk: localhost:2181(CONNECTED) 5]
WATCHER::
WatchedEvent state:SyncConnected
type:NodeChildrenChanged path:/

获取节点信息

[zk: localhost:2181(CONNECTED) 4] get
/wzyy
phone game

获取节点的详细信息

[zk: localhost:2181(CONNECTED) 5] get-s
/wzyy
phone game #节点中保存的数据,可以保存1MB的数据
cZxid = 0x300000005 #创建事务id。3(它是0000
0003省略表示方式)表示Leader改变过三次。
ctime = Mon Sep 1309:42:19 CST 2021#该节点的创建时间
mZxid = 0x300000005 #修改的事务id,创建后没有被修改过,使用创建时的事务id
mtime = Mon Sep 1309:42:19 CST 2021#修改此节点的时间,没有被修改过,使用时创建的时间
pZxid = 0x300000005 #记录子级节点的最大事务id
cversion =0
dataVersion =0#数据的版本号,每改一次该节点的数据,版本号加1
aclVersion =0
ephemeralOwner = 0x0 #该节点对应的session的id dataLength =10#节点中数据的长度
numChildren =0#该节点下子级节点的数量

创建普通临时节点

#创建临时节点
[zk: localhost:2181(CONNECTED) 14] create
-e /wzyy/test 'qqq'
Created /wzyy/test
[zk: localhost:2181(CONNECTED) 15] ls
/wzyy
[fashi, sheshou, test]
[zk: localhost:2181(CONNECTED) 15] quit
[root@node3 ~]# zkCli.sh
[zk: localhost:2181(CONNECTED) 15] ls
/wzyy
[fashi, sheshou] #发现子节点test小时

创建顺序节点

#创建普通顺序节点
[zk: localhost:2181(CONNECTED) 1] create -
s /wzyy/zhanshi 'putongshunxu'
Created /wzyy/zhanshi0000000003
[zk: localhost:2181(CONNECTED) 2] create -
s /wzyy/zhanshi 'putongshunxu2'
Created /wzyy/zhanshi0000000004
[zk: localhost:2181(CONNECTED) 3] ls /wzyy
[fashi, sheshou, zhanshi0000000003,
zhanshi0000000004]
#创建临时顺序节点
[zk: localhost:2181(CONNECTED) 4] create -
s -e /wzyy/tanke 'se1'
Created /wzyy/tanke0000000005

修改节点的值

[zk: localhost:2181(CONNECTED) 10] get
/wzyy/fashi
yuancheng
[zk: localhost:2181(CONNECTED) 11] set
/wzyy/fashi "yuancheng_edit"
[zk: localhost:2181(CONNECTED) 12] get
/wzyy/fashi
yuancheng

监控节点值的变化

#node4
[zk: localhost:2181(CONNECTED) 6] get -w
/wzyy/fashi
yuancheng_edit
#node3上
[zk: localhost:2181(CONNECTED) 13] set
/wzyy/fashi "yuancheng_update"
#node4
[zk: localhost:2181(CONNECTED) 7]
WATCHER::
WatchedEvent state:SyncConnected
type:NodeDataChanged path:/wzyy/fashi

删除节点

[zk: localhost:2181(CONNECTED) 14] ls
/wzyy
[fashi, sheshou, tanke0000000005,
zhanshi0000000003, zhanshi0000000004]
[zk: localhost:2181(CONNECTED) 15] delete
/wzyy/zhanshi0000000004
[zk: localhost:2181(CONNECTED) 16] ls
/wzyy
[fashi, sheshou, tanke0000000005,
zhanshi0000000003]

递归删除

[zk: localhost:2181(CONNECTED) 18] ls
/wzyy/fashi
[wangzhaojun]
[zk: localhost:2181(CONNECTED) 19] delete
/wzyy/fashi
Node not empty: /wzyy/fashi
[zk: localhost:2181(CONNECTED) 20] rmr
/wzyy/fashi #deleteall /wzyy/fashi
#建议使用deleteall进行递归删除
The command 'rmr' has been deprecated.
Please use 'deleteall' instead.
[zk: localhost:2181(CONNECTED) 21] ls
/wzyy
[sheshou, tanke0000000005,
zhanshi0000000003]

查看节点的状态

[zk: localhost:2181(CONNECTED) 22] stat
/wzyy
cZxid = 0x300000005
ctime = Mon Sep 13 09:42:19 CST 2021
mZxid = 0x300000005
mtime = Mon Sep 13 09:42:19 CST 2021
pZxid = 0x300000015
cversion = 9
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 10
numChildren = 3

3.3 Zookeeper会话(Session)

在这里插入图片描述
**定义:**客户端通过TCP协议与独立服务器或者一个集群中的某
个服务器建立TCP长连接。
特点:

  1. 会话提供顺序保障,即同一个会话中的请求以FIFO的顺序执行。如果客户端有多个并发会话,FIFO顺序在多个会话之间未必能够保持。
  2. 如果连接的Server出现问题,在没有超过Timeout时间时,可以连接其它节点。ZooKeeper客户端透明地转移一个会话到不同的服务器。
  3. 同一session期内的特性不变
  4. 当一个会话因某种原因终止,在这个会话期间创建的临时节点将会消失。
    生命周期:
    在这里插入图片描述
    Session是由谁来创建的?
    Leader:产生一个唯一的session,放到消息队列,让所有server知道
    过半机制:保证session创建成功或者失败

3.4 事件监听原理剖析

问题:客户端如何获取Zookeeper服务器上最新数据?
方式一:客户端轮询指定节点下的数据,通过网络轮询,代价很大。
在这里插入图片描述
方式二:基于通知(notification)的机制:
客户端向ZooKeeper注册需要接收通知的znode,通过对znode设置监视点(watch)来接收通知。监视点是一个单次触发的操作,意即监视点会触发一个通知。
在这里插入图片描述
对比两种方式,哪种方式好?
事件监听Watcher
Watcher 在 ZooKeeper 是一个核心功能,Watcher 可以监控目录节点的数据变化以及子节点的变化,一旦这些状态发生变化,服务器就会通知所有设置在这个目录节点上的Watcher,从而每个客户端都很快知道它所关注的目录节点的状态发生变化,而做出相应的反应。
JavaAPI:

  • 可以设置观察点的操作:exists,getChildren,getData
  • 可以触发观察的操作:create,delete,setData

3.5 工作原理

ZooKeeper的核心是原子广播,这个机制保证了各个server之间的信息同步。实现这个机制的协议叫做ZAB协议。
ZAB协议有两种模式:
1.恢复模式:当服务启动或者在领导者崩溃后,ZAB就进入了恢复模式。当领导者被选举出来,且大多数server的完成了和leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和follower以及observer具有相同的系统状态。
完成leader选举后,zk就进入ZooKeeper之间状态同步过程

  1. leader等待server连接;
  2. Follower连接leader,将最大的zxid发送给leader;
  3. Leader根据follower的zxid确定同步点;
  4. 完成同步后通知follower 已经成为uptodate状态;
  5. Follower收到uptodate消息后,又可以重新接受client的请求进行服务了。
    在这里插入图片描述
    2.广播模式
    广播模式需要保证proposal被按顺序处理,因此zk采用了递增的事务id号(zxid)来保证。所有的提议(proposal)都在被提出的时候加上了zxid(比如:0x1000000300000002)。
    epoch也称为纪元数字。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,低32位是个递增计数。

在这里插入图片描述
1 在Client向Follwer发出一个写的请求
2 Follwer把请求发送给Leader
3 Leader接收到以后开始发起投票并通知Follwer进行投票
4 Follwer把投票结果发送给Leader
5 Leader将结果汇总后如果需要写入,则开始写入同时把写入操作通知给Follwer,然后commit
6 Follwer把请求结果返回给Client

3.6 Zookeeper集群的特点

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_63953077/article/details/130493371