ZooKeeper基本讲解及使用

本文摘录于:http://blog.51cto.com/tchuairen/1859494;https://blog.csdn.net/peace1213/article/details/52571445。感谢作者,侵删。

一、ZooKeeper概述

ZooKeeper是一种为分布式应用所设计的高可用、高性能且一致的开源协调服务,它提供了一项基本服务:分布式锁服务。由于ZK开源的特性,后来我们的开发者在分布式锁的基础上,摸索出了其他使用方法:配置维护、组服务、分布式消息队列、分布式通知/协调等。https://cwiki.apache.org/confluence/display/ZOOKEEPER/Index.

ZK是基于内存同步数据的,所以集群内的节点其内存中的数据结构完全相同,因此效率非常高。

ZooKeeper的几个特性决定了它能够用在大型的分布式的系统中:

1、顺序一致性:从同一客户端发出的事务请求,最终将会严格按照其发起顺序被应用到ZK中。

2、原子性:所有事务请求的处理结果在整个集群所有机器上的应用情况是一致的,即要么整个集群中所有机器都应用了某一事务,要么都没应用,一定不会出现部分机器应用了该事务,另外一部分没应用的情况。

3、单一视图:无论客户端连接的是哪个zookeeper的服务,其看到的服务端数据模型都是一致的。

4、可靠性:一旦服务端成功地应用了某种事务,并完成对客户端响应,那么该事务所引起的服务端状态变更会一直保留下来,除非有另一事务对其进行了更改。

5、实时性:zookeeper并不是强一致性,只能保证顺序一致性和最终一致性,只能称为达到了伪实时性。

二、ZooKeeper的数据模型

zookeeper拥有一个层次的命名空间,这个和标准的文件系统非常相似,如图:

 

zookeeper采用树形层次结构,树中的每个节点被称为--Znode,Znode也可以拥有子节点。

引用方式:

Znode通过路径引用,如同Unix中的文件路径。必须是绝对路径,因此他们必须由斜杠字符来开头。除此之外,他们必须是唯一的,也就是说每个路径只有一个表示,因此这些路径不能改变。在ZooKeeper中,路径由Unicode字符串组成,并且有一些限制。字符串"/zookeeper"用以保存管理信息,比如关键配额信息。

Znode结构:

Znode兼具文件和目录两种特点。既像文件一样维护着数据、元信息、ACL、时间戳等数据结构,又像目录一样可以作为路径标识的一部分。每个Znode由三个部分组成:

1、stat:此为状态信息,描述该Znode版本、权限等信息。

2、data:与该Znode关联的数据

3、children:该Znode下的节点

 

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

三、节点类型

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

临时节点:该节点的生命周期依赖于创建它的会话。一旦会话结束,临时节点将被自动删除,当然也可以手动删除。虽然每个临时节点都会绑定到一个客户端会话,但它们对所有客户端都是可见的。另外ZooKeeper的临时节点不允许再有子节点。

永久节点:该节点的生命周期不依赖于会话,并且只有在客户端显示执行删除操作时,它们才能被删除。

顺序节点:当创建Znode的时候,用户可以请求在Zookeeper的路径结尾添加一个递增的计数。这个计数对于此节点的父节点来说是唯一的,它的格式为"%10d"(10位数,没有数值的数位用0补充,例如"0000000001"),当数值大于232-1的时候,计数器将溢出。

监视器:客户端可以在节点上设置watch。当节点状态发生改变时(Znode的增、删、改)将会触发watch对应的操作。当watch被触发时,Zookeeper将会对客户端发送且仅发送一条通知,因为watch只能被触发一次,这样可以减少网络流量。

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

1、Zxid

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

(1)cZxid: 是节点的创建时间所对应的Zxid格式时间戳。

(2)mZxid:是节点的修改时间所对应的Zxid格式时间戳。

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

2、版本号

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

(1)version:节点数据版本号

(2)cversion:子节点版本号

(3)aversion:节点所拥有的ACL版本号

ZooKeeper节点属性:

 

 四、分布式锁的应用

主要步骤是:
1.建立一个节点,假如名为:lock 。节点类型为持久节点(PERSISTENT)
2.每当进程需要访问共享资源时,会调用分布式锁的lock()或tryLock()方法获得锁,这个时候会在第一步创建的lock节点下建立相应的顺序子节点,节点类型为临时顺序节点(EPHEMERAL_SEQUENTIAL),通过组成特定的名字name+lock+顺序号。
3.在建立子节点后,对lock下面的所有以name开头的子节点进行排序,判断刚刚建立的子节点顺序号是否是最小的节点,假如是最小节点,则获得该锁对资源进行访问。
4.假如不是该节点,就获得该节点的上一顺序节点,并给该节点是否存在注册监听事件。同时在这里阻塞。等待监听事件的发生,获得锁控制权。
5.当调用完共享资源后,调用unlock()方法,关闭zk,进而可以引发监听事件,释放该锁。
实现的分布式锁是严格的按照顺序访问的并发锁。

posted @ 2018-10-24 22:13  rayallenbj  阅读(1056)  评论(0编辑  收藏  举报