Zookeeper简介
zookeeper是一个为分布式应用所设计的开源协调服务,提供同步,配置管理,分组和命名服务。
设计目标:
- 简单化
zookeeper允许分布式的进程通过共享体系内的命名空间来进行协调,其组织与标准的文件系统非常相似,是由一些数据寄存器组成,在zookeeper中,这些寄存器称之为znode。zookeeper的数据存放在内存当中,因此其具有高吞吐量和低延迟。 - 健壮性
zookeeper维护着一个处于内存中的状态镜像,一个位于存储器中的交换日志和快照。只要大部分服务器可用,那么zookeeper服务就是可用的。服务器与客户端之间通过TCP连接,并通过TCP连接来发送请求,获得相应,获取检测事件及发送心跳。 - 有序性
zookeeper可以为每一次更新操作赋予一个版本号,且此版本号全局有效,不存在重复情况。 - 速度优势
zookeeper在读取主要负载的时候,特别快,当读工作比写工作多的时候,执行性能更好。
zookeeper的命名空间
zookeeper的命名空间与标准的文件系统比较相似,是通过斜线分隔的路径名序列组成。
zookeeper的数据模型
zookeeper具有分层的命名空间,每个节点可以有数据关联作为他们的子节点,就如一个文件系统允许文件作为目录或目录可以存放数据。
znode:zookeeper节点
zookeeper树形结构中,每个节点都可以称之为znode,znode维护着一个属性结构,它包含数据的版本号,时间戳等状态信息。
znode的特征
- Watches
客户端在节点上设置watch(监视器),当节点的状态发生改变,将会触发watch对应的操作。当watch被触发时,zookeeper将会向客户端发送且仅发送一个通知,因为watch只能被触发一次。 - 数据访问
znode具有原子性,每一个znode的数据将被原子地读写。读取数据的时候,将读取与znode相关的所有数据,写操作将替换掉所有的数据,每个节点都拥有自己的ACL。 - 临时节点
zookeeper中节点分为两种,临时和永久,节点类型在创建之初即被确定,不能改变。临时节点依赖于当前的会话,会话结束,临时节点将被删除。 - 顺序节点(唯一性保证)
父节点会为第一个子节点维护一份记录,会记录每个子节点创建的先后顺序。
zookeeper中的时间
zk中有多种时间记录的形式,其中包括:
- Zxid
对节点状态改变的每一个操作,都将使节点收到一个zxid格式的时间戳,且时间戳全局有序。 - 版本号
对节点的每一个操作,都将使节点版本号增加,每个节点维护三个版本号:version(节点数据版本号),cversion(子节点版本号),aversion(节点所拥有的ACL版本号)。
zookeeper会话状态
zk客户端通过zk服务器建立一个会话,当连接成功,则状态变为CONNECTED,一般只有两种状态,CONNECTED和CLOSED。
zookeeper状态转换图:
zookeeper的一致性保证
- 顺序一致性
客户端的更新顺序与他们被发送的顺序相一致。 - 原子性
更新操作要么成功,要么失败,没有第三种结果。 - 单系统镜像
无论客户端连接到哪一个服务器,他将看到相同的zk视图 - 可靠性
一旦一个更新操作被应用,那么客户端再次更新之前,某值将不会改变。
- 客户端成功获取正确的返回代码,则表名更新已成功,不能够获得返回代码,那么客户端将无法知道更新操作是否成功。
- 故障恢复时,任何客户端都能够看到的执行成功的更新操作将不会回滚。
- 实时性
在特定时间内,客户端看到系统需要被保证是实时的(在十几秒的时间里)。在此时间段内,任何系统的改变将被客户端看到的,或者被客户端则测到。
zookeeper锁服务
zookeeper加锁方式:
- 客户端调用create()方法,创建“locknode/lock-”连续的临时节点,此节点为类型为sequence(连续)和ephemeral(临时)。也就是说,创建的节点为临时节点,并且所有的节点连续编号,即为“lock-i”的格式。
- 在创建的锁节点上调用getChildren()方法,以获取锁目录下的最小编号节点,并且不设置watch。
- 若步骤2中获取的节点恰好是步骤1中客户端创建的节点,那么此客户端会获得该种类型的锁,然后退出操作。
- 客户端在锁目录上调用exists()方法,并且设置watch来监视锁目录下序号相对自己次小的连续临时节点的状态变化。
- 如果监视节点状态发生变化,则跳转到步骤2,继续进行后续的操作,直到退出锁竞争。
zookeeper的锁机制流程如图: