ZooKeeper基础

初识ZooKeeper

ZooKeeper介绍

ZooKeeper是一个开放源代码的分布式协调服务,由雅虎创建,是Google Chubby的开源实现。ZooKeeper的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并以一系列简单易用的接口提供给用户使用。

ZooKeeper是什么

ZooKeeper可以保证如下分布式一致性特性:

  • 顺序一致性
  • 原子性
  • 单一视图
  • 可靠性
  • 实时性

ZooKeeper的设计目标

ZooKeeper致力于提供一个高性能、高可用,且具有严格的顺序访问控制能力的分布式协调服务。

  • 简单的数据模型
  • 可以构建集群
  • 顺序访问
  • 高性能

ZooKeeper的基本概念

集群角色

ZooKeeper没有沿用船用的slave/master概念,而是引入了Leader、Follower和Observer三种角色。ZooKeeper集群中的所有机器通过一个Leader选举过程来选定一台被称为“Leader”的机器,Leader服务器为客户端提供读和写服务。Follower和Observer都能提供读服务,唯一的区别在于Observer机器不参与Leader选举过程,也不参与写操作的“过半写成功”策略。

会话 Session

客户端和服务器之间建立一个TCP长连接,通过心跳检测与服务器保持有效的会话,也能够向ZooKeeper服务器发生请求并接受响应,通过来能够通过该连接接收来自服务器的Watch时间通知。

数据节点 Znode

指数据模型中的数据单元。ZooKeeper将所有数据村粗在内存中,数据模型是一棵树,由斜杠进行分隔的路径就是一个Znode,例如/foo/path1.每个Znode上都会保存自己的数据内容,同事还会保存一系列属性信息。

  • 持久节点:需要主动进行Znode移除操作。
  • 临时结点:它的生命周期和客户端会话绑定。

版本

每个Znode都会维护一个叫做Stat的数据结构,Stat中记录了这个Znode的三个数据版本,分别是version-当前Znode的版本,cversion-当前Znode子节点的版本,aversion-当前Znode的acl版本。

Watcher

事件监听器。ZooKeeper允许用户在指定节点上注册一些Watcher,并且在一些特定事件触发的时候,ZooKeeper服务端会将时间通知到感兴趣的客户端上去,该机制是ZooKeeper实现分布式协调服务的重要特性。

ACL

access control lists来进行权限控制。ZooKeeper定义了如下5种权限:

  • CREATE 创建子节点的权限
  • READ 获取节点数据和子节点列表的权限
  • WRITE 更新节点数据的权限0
  • DELETE 删除子节点的权限
  • ADMIN 设置节点ACL的权限

ZooKeeper的ZAB协议

ZooKeeper Atomic Broadcast, ZooKeeper原子消息广播协议。ZooKeeper使用一个单一的主进程来接收并处理客户端的所有事务请求,并采用ZAB的原子广播协议,将服务器数据的状态变更以书屋Proposal的形式广播到所有的副本进程上去。

ZAB协议的核心是定义了对于那些会改变ZooKeeper服务器数据状态的事务请求的处理方式,即:

所有事务请求必须由一个全局唯一的服务器来协调处理,这样的服务器被称为Leader服务器,而余下的其他服务器则称为Follower服务器。Leader服务器负责将一个客户端事务请求转换成一个事务Proposal(提议),并将该Proposal分发给集群中所有的Follower服务器。之后Leader服务器需要等待所有Follower服务器的反馈,一旦超过半数的Follower服务器进行了正确的反馈后,那么Leader就会再次向所有的Follower服务器分发Commit消息,要求其将前一个Proposal进行提交。

协议介绍

消息广播

针对客户端的事务请求,Leader服务器会为其生成对应的事务Proposal,并将其发送给集群中其余所有的机器,然后再分别收集各自的选票,最后进行事务提交。

崩溃恢复

核心:能够确保提交已经被Leader提交的事务Proposal,同时丢弃已经被跳过的事务Proposal。

算法描述

  • 发现 discovery 选取最大的epoch
  • 同步 synchronization prepare commit
  • 广播 broadcast

Zookeeper安装

在windows上部署伪集群模式的链接,注意需要给每个机器的data目录下添加一个myid文件。
http://blog.csdn.net/morning99/article/details/40426133

启动zkCli.cmd -server ip:host

Java客户端API使用

创建会话

Zookeeper zk = new Zookeeper();

节点类型共有四种

  • 持久 PERSITENT
  • 持久顺序 PERSITENT_SEQUENTIAL
  • 临时 EPHEMERAL
  • 临时顺序 EPHEMERAL

创建节点

zkClient.create()

Zookeeper不支持递归创建,即无法在父节点不存在的情况下创建一个子节点。

删除节点

zkClient.delete()

在Zookeeper中,只允许删除叶子节点。也就是说如果一个节点存在至少一个子节点的话,那么该节点将无法被直接删除,必须先删除掉其所有子节点。

读取数据

zkClient.getChildren()

调用getChildren()获取到的节点列表,都是数据节点的相对节点路径。

Zookeeper服务端在向客户端发送Watcher”NodeChildrenChanged”事件通知的时候,仅仅只会发出一个通知,而不会把节点的变化情况发送给客户端,需要客户端自己重新获取。另外,由于Watcher通知是一次性的,即一旦触发一次通知后,该Watcher就失效了,因此客户端需要反复注册Watcher。

zkClient.getData()

节点的数据内容或是节点的数据版本编号,都被看作是Zookeeper节点的编号。

更新数据

setData(final String path, byte date[], int version)

CAS理论,对于值V,每次更新前都会比对其值是否是预期值A,只有符合预期,才会将V原子化地更新到新值B。

如果传入的version为-1,就是告诉Zookeeper服务器,客户端需要基于数据的最新版本进行更新操作,没有原子性要求。

检测节点是否存在

zkClient.exists()

  • 无论指定节点是否存在,通过调用exists接口都可以注册Watcher。
  • exists接口中注册的Watcher,能够对节点创建、节点删除和节点数据更新事件进行监听
  • 对于指定节点的子节点的各种变化,都不会通知客户端。

权限控制

当客户端对一个数据节点添加了权限信息后,对于删除操作而言,其作用范围是其子节点。也就是说,当我们对一个数据节点添加权限信息后,依然可以自由地删除这个节点,但是对于这个节点的子节点,就必须使用相应的权限信息才能够删除掉它。