Zookeeper的基本概念和重要特性

1. 什么是Zookeeper

Zookeeper是大数据生态圈中的重要组件,若是你作过相关开发的话,应该常常能看到它的身影。其由雅虎开源并成为Apache的顶级项目。用一句话对其进行定义就是:它是一套高吞吐的分布式协调系统。从中咱们能够知道Zookeeper至少具备如下特色:node

  • 1.Zookeeper的主要做用是为分布式系统提供协调服务,包括但不限于:分布式锁,统一命名服务,配置管理,负载均衡,主控服务器选举以及主从切换等。

  • 2.Zookeeper自身一般也以分布式形式存在。一个Zookeeper服务一般由多台服务器节点构成,只要其中超过一半的节点存活,Zookeeper便可正常对外提供服务,因此Zookeeper也暗含高可用的特性。客户端能够经过TCP协议链接至任意一个服务端节点请求Zookeeper集群提供服务,而集群内部如何通讯以及如何保持分布式数据一致性等细节对客户端透明。以下图所示

  • 3.Zookeeper是以高吞吐量为目标进行设计的,故而在读多写少的场合有很是好的性能表现。以下图所示

纵轴为每秒响应的客户端请求数,横轴为读请求所占百分比。从图中能够清晰的看到,随着读请求所占百分比的提升,Zookeeper的QPS也不断提升。
Zookeeper具备高吞吐特性的主要缘由有如下几点:算法

1.Zookeeper集群的任意一个服务端节点均可以直接响应客户端的读请求(写请求会不同些,下面会详谈),而且能够经过增长节点进行横向扩展。这是其吞吐量高的主要缘由服务器

2.Zookeeper将全量数据存储于内存中,从内存中读取数据不须要进行磁盘IO,速度要快得多。并发

3.Zookeeper放松了对分布式数据的强一致性要求,即不保证数据实时一致,容许分布式数据通过一个时间窗口达到最终一致,这也在必定程度上提升了其吞吐量。负载均衡

而写请求,或者说事务请求,由于要进行不一样服务器结点间状态的同步,必定程度上会影响其吞吐量。故而简单的增长Zookeeper的服务器节点数量,对其吞吐量的提高并不必定能起到正面效果。服务器节点增长,有利于提高读请求的吞吐量,但会延长服务器节点数据的同步时间,必须视具体状况在这二者之间取得一个平衡。分布式

2. Zookeeper集群角色

在Zookeeper集群中,分别有Leader,Follower和Observer三种类型的服务器角色。性能

  • Leader
    Leader服务器在整个正常运行期间有且仅有一台,集群会经过选举的方式选举出Leader服务器,由它同统一处理集群的事务性请求以及集群内各服务器的调度。大数据

  • Follower
    Follower的主要职责有如下几点:
    • 1.参与Leader选举投票
    • 2.参与事务请求Proposal的投票
    • 3.处理客户端非事务请求(读),并转发事务请求(写)给Leader服务器。
  • Observer
    Observer是弱化版的Follower。其像Follower同样可以处理非事务也就是读请求,并转发事务请求给Leader服务器,可是其不参与任何形式的投票,不论是Leader选举投票仍是事务请求Proposal的投票。引入这个角色主要是为了在不影响集群事务处理能力的前提下提高集群的非事务处理的吞吐量。设计

3. Zookeeper的数据模型

Zookeeper将数据存储于内存中,具体而言,Znode是存储数据的最小单元。而Znode被以层次化的结构进行组织,形容一棵树。其对外提供的视图相似于Unix文件系统。树的根Znode节点至关于Unix文件系统的根路径。正如Unix中目录下能够有子目录同样,Znode结点下也能够挂载子结点,最终造成以下所示结构。

以文件系统进行类比的话,Znode自然具备目录和文件两重属性:即Znode既能够当作文件往里面写东西,又能够当作目录在下面挂载其余Znode。固然,因为Znode具备不一样的类型,后半部分并不彻底准确。

3.1 Znode的类型

Znode按其生命周期的长短能够分为持久结点(PERSISTENT)和临时结点(EPHEMERAL);在建立时还可选择是否由Zookeeper服务端在其路径后添加一串序号用来区分同一个父结点下多个结点建立的前后顺序。
通过组合就有如下4种Znode结点类型

  • 1.持久结点(PERSISTENT)
    最多见的Znode类型,一旦建立将在一直存在于服务端,除非客户端经过删除操做进行删除。持久结点下能够建立子结点。

  • 2.持久顺序结点(PERSISTENT_SEQUENTIAL)
    在具备持久结点基本特性的基础上,会经过在结点路径后缀一串序号来区分多个子结点建立的前后顺序。这工做由Zookeeper服务端自动给咱们作,只要在建立Znode时指定结点类型为该类型。

  • 3.临时结点(EPHEMERAL)
    临时结点的生命周期和客户端会话保持一致。客户端段会话存在的话临时结点也存在,客户端会话断开则临时结点会自动被服务端删除。临时结点下不能建立子结点。

  • 4.临时顺序结点(EPHEMERAL_SEQUENTIAL)
    具备临时结点的基本特性,又有顺序性。

3.2 Znode的结构

Znode结构主要由存储于其中的数据信息和状态信息两部分构成,经过get 命令获取一个Znode结点的信息以下

第一行存储的是ZNode的数据信息,从cZxid开始就是Znode的状态信息
Znode的状态信息比较多,挑几个比较重要的讲

  • czxid:
    即Created ZXID,表示建立该Znode结点的事务ID

  • mzxid:
    即Modified ZXID,表示最后一次更新该结点的事务ID

  • version
    该Znode结点的版本号。每一个Znode结点被建立时版本号都为0,每更新一次都会致使版本号加1,即便更新先后Znode存储的值没有变化版本号也会加1。version值能够形象的理解为Znode结点被更新的次数。Znode状态信息中的版本号信息,使得服务端能够对多个客户端对同一个Znode的更新操做作并发控制。整个过程和java中的CAS有点像,是一种乐观锁的并发控制策略,而version值起到了冲突检测的功能。客户端拿到Znode的version信息,并在更新时附上这个version信息,服务端在更新Znode时必须必须比较客户端的version和Znode的实际version,只有这两个version一致时才会进行修改。

4. Zookeeper的事件监听机制

Zookeeper中能够经过Watcher来实现事件监听机制。客户端能够向服务端注册Watcher用以监听某些事件,一旦该事件发生,服务端即会向客户端发送一个通知。其主要工做流程以下图所示

具体而言,Watcher是Zookeeper原生API中提供的事件监听接口,用户要实现事件监听必须实现该接口并重写process(WatchedEvent event)方法,该方法定义了客户端在接收到服务端事件通知后的回调逻辑。究竟服务端的什么事件能够被监听?按通知状态划分有SyncConnected,Disconnected,Expired,AuthFailed等好多种,这里主要讲下SyncConnected状态下的几种事件类型:

  • Node(-1)
    客户端与服务端成功创建会话

  • NodeCreated(1)
    Watcher监听的对应Znode被建立

  • NodeDeleted(2)
    Watcher监听的Znode被删除

  • NodeDataChanged(3)
    Watcher监听的Znode的数据内容被改变,注意即便变动先后的数据内容彻底同样也会触发该事件,或者理解成该事件的触发条件是Znode的版本号变动也没问题

  • NodeChildrenChanged(4)
    Watcher监听的对应Znode的子结点发生变动

Zookeeper的事件监听机制有如下特性:

  • 1.当监听器监听的事件被触发,服务端会发送通知给客户端,但通知信息中不包括事件的具体内容。以监听ZNode结点数据变化为例,当Znode的数据被改变,客户端会收到事件类型为NodeDataChanged的通知,但该Znode的数据改变成了什么客户端没法从通知中获取,须要客户端在收到通知后手动去获取。

  • 2.Watcher是一次性的。一旦被触发将会失效。若是须要反复进行监听就须要反复进行注册。这么设计是为了减轻服务端的压力,可是对开发者而言倒是至关不友好,不过不用着急,能够经过一些Zookeeper的开源客户端轻松实现对某一事件的永久监听。

5. Zookeeper如何保证分布式数据一致性——ZAB协议

Zookeeper采用ZAB(Zookeeper Atomic Broadcast)协议来保证分布式数据一致性。ZAB并非一种通用的分布式一致性算法,而是一种专为Zookeeper设计的崩溃可恢复的原子消息广播算法。ZAB协议包括两种基本模式:崩溃恢复模式和消息广播模式。崩溃恢复模式主要用来在集群启动过程,或者Leader服务器崩溃退出后进行新的Leader服务器的选举以及数据同步;消息广播模式主要用来进行事务请求的处理。下面就从这两个方面来介绍

5.1 事务请求的处理流程

ZAB协议的核心是定义了对事务请求的处理方式,整个过程能够归纳以下:

  • 1.全部的事务请求都交由集群的Leader服务器来处理,Leader服务器会将一个事务请求转换成一个Proposal(提议),并为其生成一个全局递增的惟一ID,这个ID就是事务ID,即ZXID,Leader服务器对Proposal是按其ZXID的前后顺序来进行排序和处理的。
  • 2.以后Leader服务器会将Proposal放入每一个Follower对应的队列中(Leader会为每一个Follower分配一个单独的队列),并以FIFO的方式发送给Follower服务器。
  • 3.Follower服务器接收到事务Proposal后,首先以事务日志的方式写入本地磁盘,而且在成功后返回Leader服务器一个ACK响应。
  • 4.Leader服务器只要收到过半Follower的ACK响应,就会广播一个Commit消息给Follower以通知其进行Proposal的提交,同时Leader自身也会完成Proposal的提交。

整个过程以下图所示

5.2 Leader服务器的选举流程

当集群中不存在Leader服务器时集群会进行Leader服务器的选举,这一般存在于两种状况:1.集群刚启动时 2.集群运行时,但Leader服务器因故退出。集群中的服务器会向其余全部的Follower服务器发送消息,这个消息能够形象化的称之为选票,选票主要由两个信息组成,所推举的Leader服务器的ID(即配置在myid文件中的数字),以及该服务器的事务ID,事务表示对服务器状态变动的操做,一个服务器的事务ID越大,则其数据越新。整个过程以下所述:

  • 1.Follower服务器投出选票(SID,ZXID),第一次每一个Follower都会推选本身为Leader服务器,也就是说每一个Follower第一次投出的选票是本身的服务器ID和事务ID。
  • 2.每一个Follower都会接收到来自于其余Follower的选票,它会基于以下规则从新生成一张选票:比较收到的选票和本身的ZXID的大小,选取其中最大的;若ZXID同样则选取SID即服务器ID最大的。最终每一个服务器都会从新生成一张选票,并将该选票投出去。

这样通过多轮投票后,若是某一台服务器获得了超过半数的选票,则其将当前选为Leader。由以上分析可知,Zookeeper集群对Leader服务器的选择具备偏向性,偏向于那些ZXID更大,即数据更新的机器。

整个过程以下图所示

6. Zookeeper如何进行服务器故障的容错

Zookeeper经过事务日志和数据快照来避免由于服务器故障致使的数据丢失。

  • 事务日志是指服务器在更新内存数据前先将事务操做以日志的方式写入磁盘,Leader和Follower服务器都会记录事务日志。
  • 数据快照是指周期性经过深度遍历的方式将内存中的树形结构数据转入外存快照中。但要注意这种快照是"模糊"的,由于可能在作快照时内存数据发生了变化。可是由于Zookeeper自己对事务操做进行了幂等性保证,故在将快照加载进内存后会经过执行事务日志的方式来说数据恢复到最新状态。

7. 参考资料

  • 《从PAXOS到ZOOKEEPER分布式一致性原理与实践》
  • 《大数据日知录》
相关文章
相关标签/搜索