4.1 初识ZooKeeper

4.1.1 ZooKeeper介绍

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

ZooKeeper是什么

ZooKeeper是一个典型的分布式数据一致性的解决方案,分布式应用程序可以基于它实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分布式锁和分布式队列等功能。
ZooKeeper可以保证如下分布式一致性特性:

  • 顺序一致性:从同一个客户端发起的事务请求,最终将会严格地按照其发起顺序被应用到ZooKeeper中去。
  • 原子性:整个集群中所有机器要么都成功应用了某一个事务,要么都没有应用,一定不会出现集群中只有部分机器应用了该事务的情况。
  • 单一视图:无论客户端连接的是哪个ZooKeeper服务器,其看到的服务端数据模型都是一致的。
  • 可靠性(持久性):一旦服务端成功应用了一个事务,并完成了对客户端的响应,那么该事务所引起的服务端状态变更将会被一直保留下来,除非另一个事务又对其进行了变更。
  • (近)实时性:ZooKeeper仅仅保证,在事务被成功应用后,一定时间段内,客户端最终一定能够从服务端上读取到最新的数据状态。

    ZooKeeper的设计目标

    目标一:简单的数据模型

    ZooKeeper使得分布式程序能够通过一个共享的、树形结构的命名空间来进行相互协调。这里所说的树型结构的名字空间,是指ZooKeeper服务器内存中的一个数据模型,其由一系列被称为ZNode的数据节点组成。该数据模型类似于一个文件系统,而ZNode之间的层级关系,就像文件系统的目录结构一样。

    目标二:可以构建集群(高可用)

    一个ZooKeeper集群通常由一组机器组成,一般3~5台机器就可以组成一个可用的ZooKeeper集群了。
    组成ZooKeeper集群的每台机器都会在内存中维护当前的服务器状态,并且每台机器之间都互相保持着通信。值得一提的是,只要集群中存在超过一半的机器能够正常工作,那么整个集群就能够正常对外服务。
    ZooKeeper的客户端程序会选择和集群中任意一台机器创建一个TCP连接,而一旦客户端和某台ZooKeeper服务器之间的连接断开后,客户端会自动连接到集群中的另一台机器上。

    目标三:顺序访问

    对于来自客户端的每个更新请求,ZooKeeper都会分配一个全局唯一的递增编号,这个编号反映了所有事务操作的先后顺序,应用程序可以使用这个特性来实现更高层次的同步原语。

    目标四:高性能

    由于ZooKeeper将全量数据存储在内存中,并直接服务于客户端的所有非事务请求,因此它尤其适用于以读操作为主的应用场景。

    4.1.2 ZooKeeper从何而来

4.1.3 ZooKeeper的基本概念

集群角色

ZooKeeper集群中的机器有如下三种角色:

  • Leader:ZooKeeper中的机器通过一个Leader选举过程来选定一台机器作为Leader。Leader为客户端提供读和写服务。
  • Follower:Follower为客户端提供服务。Follower可以参与Leader选举过程,也可以参与写操作的“过半写成功”策略。
  • Observer:Observer为客户端提供服务。与Follower不同的是,Observer不能参与Leader选举过程,也不能参与写操作的“过半写成功”策略。

    会话(Session)

    客户端会话,基于TCP长连接。

    数据节点(ZNode)

    ZooKeeper将所有数据存储在内存中,数据模型是一棵树(ZNodeTree),由斜杠(/)进行分割的路径,就是一个ZNode,例如/foo/path1。每个ZNode都会保存自己的数据内容,同时还会保存一系列属性信息。
    ZNode可以分为持久节点和临时节点两类。所谓持久节点是指一旦这个ZNode被创建了,除非主动进行ZNode的移除操作,否则这个ZNode将一直保存在ZooKeeper上。而临时节点的生命周期和客户端会话绑定,一旦客户端会话失效,那么这个客户端创建的所有临时节点都会被移除。另外,ZooKeeper还允许用户为每个节点添加一个特殊的属性:SEQUENTIAL。一旦节点被标记上这个属性,那么在这个节点被创建的时候,ZooKeeper会自动在其节点名后面追加上一个整型数字,这个整型数字是由父节点维护的自增数字

    版本

    对应于每个ZNode,ZooKeeper都会为其维护一个叫做Stat的数据结构,Stat中记录了这个ZNode的三个版本相关的信息,分别是:

  • version:当前ZNode的版本。

  • cversion:当前ZNode的子节点的版本。
  • aversion:当前ZNode的ACL版本。

    Watcher

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

    ACL

    ZooKeeper采用ACL(Access Control Lists)策略来进行权限控制。ZooKeeper定义了如下5种权限:

  • CREATE:创建子节点的权限。

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

    4.1.4 为什么选择ZooKeeper


4.2 ZooKeeper的ZAB协议

4.2.1 ZAB协议

ZooKeeper并没有完全采用Paxos算法,而是使用了一种被称为ZooKeeper Atomic Broadcast(ZAB)协议作为其一致性的核心算法。
ZooKeeper采用了主备模式。具体来讲,使用一个单一的主进程来接收并处理客户端的所有事务请求,并采用ZAB协议,将服务器数据的状态变更以事务Proposal的形式广播到所有的副本进程上去。
ZAB协议的核心是定义了对于那些会改变ZooKeeper服务器数据状态的事务请求的处理方式。即:所有事务请求都必须由一个全局唯一的服务器来协调处理,这样的服务器被称为Leader服务器,而余下的其他服务器则成为Follower服务器。Leader服务器负责将一个客户端事务请求转换成一个事务Proposal(提案),并将该Proposal分发给集群中所有的Follower服务器。之后Leader服务器需要等待所有Follower服务器的反馈,一旦超过半数的Follower服务器进行了正确的反馈后,那么Leader就会再次向所有的Follower服务器分发Commit消息,要求将前一个Proposal进行提交

4.2.2 协议介绍