zookeeper数据结构、通知

        ZooKeeper提供的名称空间非常类似于标准文件系统。名称是由斜线(/)分隔的一系列路径元素。ZooKeeper名称空间中的每个节点都由一个路径标识。

 

        树是由节点所组成,zookeeper的数据存储也同样是基于节点,这个节点叫做Znode.但是,不同于树的节点,Znode的引用方式是路径引用,类似于文件路径:/app1/p_1

        这样的层级结构,让每一个Znode节点拥有唯一的路径,就像命名空间一样对不同信息作出清晰的隔离。

ZooKeeper中节点

        ZooKeeper的节点是通过像树一样的结构来进行维护的,并且每一个节点通过路径来标示以及访问。除此之外,每一个节点还拥有自身的一些信息,包括:数据、数据长度、创建时间、修改时间等等。从这样一类既含有数据,又作为路径表标示的节点的特点中,可以看出,ZooKeeper的节点既可以被看做是一个文件,又可以被看做是一个目录,它同时具有二者的特点。为了便于表达,今后我们将使用Znode来表示所讨论的ZooKeeper节点。

       具体地说,Znode维护着数据、ACL(access control list,访问控制列表)、时间戳等交换版本号等数据结构,它通过对这些数据的管理来让缓存生效并且令协调更新。每当Znode中的数据更新后它所维护的版本号将增加,这非常类似于数据库中计数器时间戳的操作方式。

       另外Znode还具有原子性操作的特点:命名空间中,每一个Znode的数据将被原子地读写。读操作将读取与Znode相关的所有数据,写操作将替换掉所有的数据。除此之外,每一个节点都有一个访问控制列表,这个访问控制列表规定了用户操作的权限。

ZooKeeper中的节点有两种,分别为临时节点永久节点。节点的类型在创建时即被确定,并且不能改变。

  • ① 临时节点:该节点的生命周期依赖于创建它们的会话。一旦会话(Session)结束,临时节点将被自动删除,当然可以也可以手动删除。虽然每个临时的Znode都会绑定到一个客户端会话,但他们对所有的客户端还是可见的。另外,ZooKeeper的临时节点不允许拥有子节点。
  • ② 永久节点:该节点的生命周期不依赖于会话,并且只有在客户端显示执行删除操作的时候,他们才能被删除。
  • 顺序节点:当创建Znode的时候,用户可以请求在ZooKeeper的路径结尾添加一个递增的计数。这个计数对于此节点的父节点来说是唯一的,它的格式为"%10d"(10位数字,没有数值的数位用0补充,例如"0000000001")。当计数值大于2^32-1时,计数器将溢出。

Znode:

  znode包含了数据、子节点引用、访问权限等等。

  • data:Znode存储的数据信息。
  • ACL:记录Znode的访问权限,即哪些人或哪些IP可以访问本节点。
  • stat:包含Znode的各种元数据,比如事务ID、版本号、时间戳、大小等等。
  • child:当前节点的子节点引用,类似于二叉树的左孩子右孩子。

       ZooKeeper虽然可以关联一些数据,但并没有被设计为常规的数据库或者大数据存储,相反的是,它用来管理调度数据,比如分布式应用中的配置文件信息、状态信息、汇集位置等等。这些数据的共同特性就是它们都是很小的数据,通常以KB为大小单位。ZooKeeper的服务器和客户端都被设计为严格检查并限制每个Znode的数据大小至多1M,但常规使用中应该远小于此值。

ZooKeeper中的时间

ZooKeeper有多种记录时间的形式,其中包含以下几个主要属性:

(1) Zxid

致使ZooKeeper节点状态改变的每一个操作都将使节点接收到一个Zxid格式的时间戳,并且这个时间戳全局有序。也就是说,也就是说,每个对节点的改变都将产生一个唯一的Zxid。如果Zxid1的值小于Zxid2的值,那么Zxid1所对应的事件发生在Zxid2所对应的事件之前。实际 上,ZooKeeper的每个节点维护者三个Zxid值,为别为:cZxid、mZxid、pZxid。

  • cZxid: 是节点的创建时间所对应的Zxid格式时间戳。
  • ② mZxid:是节点的修改时间所对应的Zxid格式时间戳。

实现中Zxid是一个64为的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch。低32位是个递增计数

(2) 版本号 (乐观锁)

对节点的每一个操作都将致使这个节点的版本号增加。每个节点维护着三个版本号,他们分别为:

  • ① version:节点数据版本号
  • ② cversion:子节点版本号
  • ③ aversion:节点所拥有的ACL版本号

ZooKeeper节点属性

ZooKeeper服务中操作  

       更新ZooKeeper操作是有限制的。delete或setData必须明确要更新的Znode的版本号,我们可以调用exists找到。如果版本号不匹配,更新将会失败。

       更新ZooKeeper操作是非阻塞式的。因此客户端如果失去了一个更新(由于另一个进程在同时更新这个Znode),他可以在不阻塞其他进程执行的情况下,选择重新尝试或进行其他操作。

       尽管ZooKeeper可以被看做是一个文件系统,但是处于便利,摒弃了一些文件系统地操作原语。因为文件非常的小并且使整体读写的,所以不需要打开、关闭或是寻地的操作。

zookeeper的命令操作

1. create [-s] [-e] path data acl

  • -s 表示节点是否有序

  • -e 表示是否为临时节点

  • 默认情况下,是持久化节点

2. get path [watch]

  • 获得指定 path的信息

3.set path data [version]

  • 修改节点 path对应的data

  • 乐观锁的概念

  • 数据库里面有一个 version 字段去控制数据行的版本号

4.delete path [version]

  • 删除节点

stat信息

  • cversion = 0       子节点的版本号

  • aclVersion = 0     表示acl的版本号,修改节点权限

  • dataVersion = 1    表示的是当前节点数据的版本号

  • czxid    节点被创建时的事务ID

  • mzxid   节点最后一次被更新的事务ID

  • pzxid    当前节点下的子节点最后一次被修改时的事务ID

  • ctime = Sat Aug 05 20:48:26 CST 2017

  • mtime = Sat Aug 05 20:48:50 CST 2017

  • ephemeralOwner = 0x0   创建临时节点的时候,会有一个sessionId 。 该值存储的就是这个sessionid

  • dataLength = 3    数据值长度

  • numChildren = 0  子节点数

ZooKeeper会话(session)

        使用客户端来创建一个和zk服务端连接的句柄,这就是一个会话(session)。Session一旦建立,状态就是连接中(CONNECTING)状态,然后客户端会尝试去连接zk服务端,连接成功之后状态变成已连接(CONNECTED)。一般正常情况下只会有这两个状态。不过,还是会发生一些无法恢复的错误/故障,比如:session过期,认证失败,或者客户端关闭连接,这种情况下,session状态会变成关闭(CLOSED)状态。

 

       当一个session建立的时候,zk服务端会生成一个64位的数字,也就是这个session的标识(姑且称之为session id吧),zk客户端会保存这个标识。如果zk客户端因为某种原因连接到了另一个zk服务端,他会把这个session id传给新的服务端。出于安全考虑,zk服务端在创建连接时,不仅仅生成一个session id,还会同时传给zk客户端一个密码,这个session id+密码是可以被任何一个zk服务端校验的。这样,每次zk客户端重连zk服务端的时候,会同时传递session id+密码,zk服务端校验通过了才会建立连接。

Watcher( 数据变更的通知)

        ZooKeeper提供了分布式数据的发布/订阅功能。一个典型的发布/订阅模型系统定义了一种一对多的订阅关系,能够让多个订阅者同时监听某一个主题对象,当这个主题对象自身状态变化时,会通知所有订阅者,使他们能够做出相应的处理。在ZooKeeper中,引入了Watcher机制来实现这种分布式的通知功能。ZooKeeper允许客户端向服务端注册一个Watcher机制来实现这种分布式的通知功能。ZooKeeper允许客户端向服务端注册一个Watcher监听,当服务端的一些指定事件触发了这个Watcher,那么就会向指定客户端发送一个事件通知来实现分布式的通知功能。

        整个Watcher注册与通知过程如下图所示。

        从上图中,我们可以看到,ZooKeeper的Watcher机制主要包括客户端线程、客户端WatchManager和ZooKeeper服务器三部分。在具体工作流程上,简单地讲,客户端在向ZooKeeper服务器注册Watcher的同时,会将Watcher对象存储在客户端的WatchManager中。当ZooKeeper服务器端触发Watcher事件后,会向客户端发送通知,客户端线程从WatchManager中取出对应的Watcher对象来执行回调逻辑。

 

参考:https://blog.csdn.net/u011499747/article/details/78024329

https://www.cnblogs.com/wuxl360/p/5817471.html

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值