目录java
Zookeeper是大数据生态圈中的重要组件,若是你作过相关开发的话,应该常常能看到它的身影。其由雅虎开源并成为Apache的顶级项目。用一句话对其进行定义就是:它是一套高吞吐的分布式协调系统。从中咱们能够知道Zookeeper至少具备如下特色:node
纵轴为每秒响应的客户端请求数,横轴为读请求所占百分比。从图中能够清晰的看到,随着读请求所占百分比的提升,Zookeeper的QPS也不断提升。
Zookeeper具备高吞吐特性的主要缘由有如下几点:算法
1.Zookeeper集群的任意一个服务端节点均可以直接响应客户端的读请求(写请求会不同些,下面会详谈),而且能够经过增长节点进行横向扩展。这是其吞吐量高的主要缘由服务器
2.Zookeeper将全量数据存储于内存中,从内存中读取数据不须要进行磁盘IO,速度要快得多。并发
3.Zookeeper放松了对分布式数据的强一致性要求,即不保证数据实时一致,容许分布式数据通过一个时间窗口达到最终一致,这也在必定程度上提升了其吞吐量。负载均衡
而写请求,或者说事务请求,由于要进行不一样服务器结点间状态的同步,必定程度上会影响其吞吐量。故而简单的增长Zookeeper的服务器节点数量,对其吞吐量的提高并不必定能起到正面效果。服务器节点增长,有利于提高读请求的吞吐量,但会延长服务器节点数据的同步时间,必须视具体状况在这二者之间取得一个平衡。分布式
在Zookeeper集群中,分别有Leader,Follower和Observer三种类型的服务器角色。性能
Leader
Leader服务器在整个正常运行期间有且仅有一台,集群会经过选举的方式选举出Leader服务器,由它同统一处理集群的事务性请求以及集群内各服务器的调度。大数据
Observer
Observer是弱化版的Follower。其像Follower同样可以处理非事务也就是读请求,并转发事务请求给Leader服务器,可是其不参与任何形式的投票,不论是Leader选举投票仍是事务请求Proposal的投票。引入这个角色主要是为了在不影响集群事务处理能力的前提下提高集群的非事务处理的吞吐量。设计
Zookeeper将数据存储于内存中,具体而言,Znode是存储数据的最小单元。而Znode被以层次化的结构进行组织,形容一棵树。其对外提供的视图相似于Unix文件系统。树的根Znode节点至关于Unix文件系统的根路径。正如Unix中目录下能够有子目录同样,Znode结点下也能够挂载子结点,最终造成以下所示结构。
以文件系统进行类比的话,Znode自然具备目录和文件两重属性:即Znode既能够当作文件往里面写东西,又能够当作目录在下面挂载其余Znode。固然,因为Znode具备不一样的类型,后半部分并不彻底准确。
Znode按其生命周期的长短能够分为持久结点(PERSISTENT)和临时结点(EPHEMERAL);在建立时还可选择是否由Zookeeper服务端在其路径后添加一串序号用来区分同一个父结点下多个结点建立的前后顺序。
通过组合就有如下4种Znode结点类型
1.持久结点(PERSISTENT)
最多见的Znode类型,一旦建立将在一直存在于服务端,除非客户端经过删除操做进行删除。持久结点下能够建立子结点。
2.持久顺序结点(PERSISTENT_SEQUENTIAL)
在具备持久结点基本特性的基础上,会经过在结点路径后缀一串序号来区分多个子结点建立的前后顺序。这工做由Zookeeper服务端自动给咱们作,只要在建立Znode时指定结点类型为该类型。
3.临时结点(EPHEMERAL)
临时结点的生命周期和客户端会话保持一致。客户端段会话存在的话临时结点也存在,客户端会话断开则临时结点会自动被服务端删除。临时结点下不能建立子结点。
4.临时顺序结点(EPHEMERAL_SEQUENTIAL)
具备临时结点的基本特性,又有顺序性。
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一致时才会进行修改。
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的开源客户端轻松实现对某一事件的永久监听。
Zookeeper采用ZAB(Zookeeper Atomic Broadcast)协议来保证分布式数据一致性。ZAB并非一种通用的分布式一致性算法,而是一种专为Zookeeper设计的崩溃可恢复的原子消息广播算法。ZAB协议包括两种基本模式:崩溃恢复模式和消息广播模式。崩溃恢复模式主要用来在集群启动过程,或者Leader服务器崩溃退出后进行新的Leader服务器的选举以及数据同步;消息广播模式主要用来进行事务请求的处理。下面就从这两个方面来介绍
ZAB协议的核心是定义了对事务请求的处理方式,整个过程能够归纳以下:
整个过程以下图所示
当集群中不存在Leader服务器时集群会进行Leader服务器的选举,这一般存在于两种状况:1.集群刚启动时 2.集群运行时,但Leader服务器因故退出。集群中的服务器会向其余全部的Follower服务器发送消息,这个消息能够形象化的称之为选票,选票主要由两个信息组成,所推举的Leader服务器的ID(即配置在myid文件中的数字),以及该服务器的事务ID,事务表示对服务器状态变动的操做,一个服务器的事务ID越大,则其数据越新。整个过程以下所述:
这样通过多轮投票后,若是某一台服务器获得了超过半数的选票,则其将当前选为Leader。由以上分析可知,Zookeeper集群对Leader服务器的选择具备偏向性,偏向于那些ZXID更大,即数据更新的机器。
整个过程以下图所示
Zookeeper经过事务日志和数据快照来避免由于服务器故障致使的数据丢失。