ZooKeeper简介html
ZooKeeper是一个开放源码的分布式应用程序协调服务,它包含一个简单的原语集,分布式应用程序能够基于它实现同步服务,配置维护和命名服务等。node
ZooKeeper设计目的算法
1.最终一致性:client不论链接到哪一个Server,展现给它都是同一个视图,这是zookeeper最重要的性能。apache
2.可靠性:具备简单、健壮、良好的性能,若是消息m被到一台服务器接受,那么它将被全部的服务器接受。服务器
3.实时性:Zookeeper保证客户端将在一个时间间隔范围内得到服务器的更新信息,或者服务器失效的信息。但因为网络延时等缘由,Zookeeper不能保证两个客户端能同时获得刚更新的数据,若是须要最新数据,应该在读数据以前调用sync()接口。网络
4.等待无关(wait-free):慢的或者失效的client不得干预快速的client的请求,使得每一个client都能有效的等待。session
5.原子性:更新只能成功或者失败,没有中间状态。数据结构
6.顺序性:包括全局有序和偏序两种:全局有序是指若是在一台服务器上消息a在消息b前发布,则在全部Server上消息a都将在消息b前被发布;偏序是指若是一个消息b在消息a后被同一个发送者发布,a必将排在b前面。异步
ZooKeeper数据模型socket
Zookeeper会维护一个具备层次关系的数据结构,它很是相似于一个标准的文件系统,如图所示:
Zookeeper这种数据结构有以下这些特色:
1)每一个子目录项如NameService都被称做为znode,这个znode是被它所在的路径惟一标识,如Server1这个znode的标识为/NameService/Server1。
2)znode能够有子节点目录,而且每一个znode能够存储数据,注意EPHEMERAL(临时的)类型的目录节点不能有子节点目录。
3)znode是有版本的(version),每一个znode中存储的数据能够有多个版本,也就是一个访问路径中能够存储多份数据,version号自动增长。
4)znode的类型:
5)znode能够被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化能够通知设置监控的客户端,这个是Zookeeper的核心特性,Zookeeper的不少功能都是基于这个特性实现的。
6)ZXID:每次对Zookeeper的状态的改变都会产生一个zxid(ZooKeeper Transaction Id),zxid是全局有序的,若是zxid1小于zxid2,则zxid1在zxid2以前发生。
ZooKeeper Session
Client和Zookeeper集群创建链接,整个session状态变化如图所示:
若是Client由于Timeout和Zookeeper Server失去链接,client处在CONNECTING状态,会自动尝试再去链接Server,若是在session有效期内再次成功链接到某个Server,则回到CONNECTED状态。
注意:若是由于网络状态很差,client和Server失去联系,client会停留在当前状态,会尝试主动再次链接Zookeeper Server。client不能宣称本身的session expired,session expired是由Zookeeper Server来决定的,client能够选择本身主动关闭session。
ZooKeeper Watch
Zookeeper watch是一种监听通知机制。Zookeeper全部的读操做getData(), getChildren()和 exists()均可以设置监视(watch),监视事件能够理解为一次性的触发器,官方定义以下: a watch event is one-time trigger, sent to the client that set the watch, whichoccurs when the data for which the watch was set changes。Watch的三个关键点:
*(一次性触发)One-time trigger
当设置监视的数据发生改变时,该监视事件会被发送到客户端,例如,若是客户端调用了getData("/znode1", true) 而且稍后 /znode1 节点上的数据发生了改变或者被删除了,客户端将会获取到 /znode1 发生变化的监视事件,而若是 /znode1 再一次发生了变化,除非客户端再次对/znode1 设置监视,不然客户端不会收到事件通知。
*(发送至客户端)Sent to the client
Zookeeper客户端和服务端是经过 socket 进行通讯的,因为网络存在故障,因此监视事件颇有可能不会成功地到达客户端,监视事件是异步发送至监视者的,Zookeeper 自己提供了顺序保证(ordering guarantee):即客户端只有首先看到了监视事件后,才会感知到它所设置监视的znode发生了变化(a client will never see a change for which it has set a watch until it first sees the watch event)。网络延迟或者其余因素可能致使不一样的客户端在不一样的时刻感知某一监视事件,可是不一样的客户端所看到的一切具备一致的顺序。
*(被设置 watch 的数据)The data for which the watch was set
这意味着znode节点自己具备不一样的改变方式。你也能够想象 Zookeeper 维护了两条监视链表:数据监视和子节点监视(data watches and child watches) getData() 和exists()设置数据监视,getChildren()设置子节点监视。或者你也能够想象 Zookeeper 设置的不一样监视返回不一样的数据,getData() 和 exists() 返回znode节点的相关信息,而getChildren() 返回子节点列表。所以,setData() 会触发设置在某一节点上所设置的数据监视(假定数据设置成功),而一次成功的create() 操做则会出发当前节点上所设置的数据监视以及父节点的子节点监视。一次成功的 delete操做将会触发当前节点的数据监视和子节点监视事件,同时也会触发该节点父节点的child watch。
Zookeeper 中的监视是轻量级的,所以容易设置、维护和分发。当客户端与 Zookeeper 服务器失去联系时,客户端并不会收到监视事件的通知,只有当客户端从新链接后,若在必要的状况下,之前注册的监视会从新被注册并触发,对于开发人员来讲这一般是透明的。只有一种状况会致使监视事件的丢失,即:经过exists()设置了某个znode节点的监视,可是若是某个客户端在此znode节点被建立和删除的时间间隔内与zookeeper服务器失去了联系,该客户端即便稍后从新链接 zookeeper服务器后也得不到事件通知。
Consistency Guarantees
Zookeeper是一个高效的、可扩展的服务,read和write操做都被设计为快速的,read比write操做更快。
顺序一致性(Sequential Consistency):从一个客户端来的更新请求会被顺序执行。
原子性(Atomicity):更新要么成功要么失败,没有部分红功的状况。
惟一的系统镜像(Single System Image):不管客户端链接到哪一个Server,看到系统镜像是一致的。
可靠性(Reliability):更新一旦有效,持续有效,直到被覆盖。
时间线(Timeliness):保证在必定的时间内各个客户端看到的系统信息是一致的。
ZooKeeper的工做原理
在zookeeper的集群中,各个节点共有下面3种角色和4种状态:
Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫作Zab协议(ZooKeeper Atomic Broadcast protocol)。Zab协议有两种模式,它们分别是恢复模式(Recovery选主)和广播模式(Broadcast同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和leader的状态同步之后,恢复模式就结束了。状态同步保证了leader和Server具备相同的系统状态。
为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。全部的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。
每一个Server在工做过程当中有4种状态:
LOOKING:当前Server不知道leader是谁,正在搜寻。
LEADING:当前Server即为选举出来的leader。
FOLLOWING:leader已经选举出来,当前Server与之同步。
OBSERVING:observer的行为在大多数状况下与follower彻底一致,可是他们不参加选举和投票,而仅仅接受(observing)选举和投票的结果。
Leader Election
当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式须要从新选举出一个新的leader,让全部的Server都恢复到一个正确的状态。Zk的选举算法有两种:一种是基于basic paxos实现的,另一种是基于fast paxos算法实现的。系统默认的选举算法为fast paxos。先介绍basic paxos流程:
1.选举线程由当前Server发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的Server;
2.选举线程首先向全部Server发起一次询问(包括本身);
3.选举线程收到回复后,验证是不是本身发起的询问(验证zxid是否一致),而后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(id,zxid),并将这些信息存储到当次选举的投票记录表中;
4.收到全部Server回复之后,就计算出zxid最大的那个Server,并将这个Server相关信息设置成下一次要投票的Server;
5.线程将当前zxid最大的Server设置为当前Server要推荐的Leader,若是此时获胜的Server得到n/2 + 1的Server票数,设置当前推荐的leader为获胜的Server,将根据获胜的Server相关信息设置本身的状态,不然,继续这个过程,直到leader被选举出来。
经过流程分析咱们能够得出:要使Leader得到多数Server的支持,则Server总数必须是奇数2n+1,且存活的Server的数目不得少于n+1.
每一个Server启动后都会重复以上流程。在恢复模式下,若是是刚从崩溃状态恢复的或者刚启动的server还会从磁盘快照中恢复数据和会话信息,zk会记录事务日志并按期进行快照,方便在恢复时进行状态恢复。
fast paxos流程是在选举过程当中,某Server首先向全部Server提议本身要成为leader,当其它Server收到提议之后,解决epoch和zxid的冲突,并接受对方的提议,而后向对方发送接受提议完成的消息,重复这个流程,最后必定能选举出Leader。
Leader工做流程
Leader主要有三个功能:
1.恢复数据;
2.维持与follower的心跳,接收follower请求并判断follower的请求消息类型;
3.follower的消息类型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根据不一样的消息类型,进行不一样的处理。
PING消息是指follower的心跳信息;REQUEST消息是follower发送的提议信息,包括写请求及同步请求;
ACK消息是follower的对提议的回复,超过半数的follower经过,则commit该提议;
REVALIDATE消息是用来延长SESSION有效时间。
Follower工做流程
Follower主要有四个功能:
1. 向Leader发送请求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息);
2.接收Leader消息并进行处理;
3.接收Client的请求,若是为写请求,发送给Leader进行投票;
4.返回Client结果。
Follower的消息循环处理以下几种来自Leader的消息:
1.PING消息:心跳消息
2.PROPOSAL消息:Leader发起的提案,要求Follower投票
3.COMMIT消息:服务器端最新一次提案的信息
4.UPTODATE消息:代表同步完成
5.REVALIDATE消息:根据Leader的REVALIDATE结果,关闭待revalidate的session仍是容许其接受消息
6.SYNC消息:返回SYNC结果到客户端,这个消息最初由客户端发起,用来强制获得最新的更新。
Zab: Broadcasting State Updates
Zookeeper Server接收到一次request,若是是follower,会转发给leader,Leader执行请求并经过Transaction的形式广播此次执行。Zookeeper集群如何决定一个Transaction是否被commit执行?经过“两段提交协议”(a two-phase commit):
Zab协议保证:
“两段提交协议”最大的问题是若是Leader发送了PROPOSAL消息后crash或暂时失去链接,会致使整个集群处在一种不肯定的状态(follower不知道该放弃此次提交仍是执行提交)。Zookeeper这时会选出新的leader,请求处理也会移到新的leader上,不一样的leader由不一样的epoch标识。切换Leader时,须要解决下面两个问题:
1. Never forget delivered messages
Leader在COMMIT投递到任何一台follower以前crash,只有它本身commit了。新Leader必须保证这个事务也必须commit。
2. Let go of messages that are skipped
Leader产生某个proposal,可是在crash以前,没有follower看到这个proposal。该server恢复时,必须丢弃这个proposal。
Zookeeper会尽可能保证不会同时有2个活动的Leader,由于2个不一样的Leader会致使集群处在一种不一致的状态,因此Zab协议同时保证:
这里的quorum是一半以上的Server数目,确切的说是有投票权力的Server(不包括Observer)。
总结:简单介绍了Zookeeper的基本原理,数据模型,Session,Watch机制,一致性保证,Leader Election,Leader和Follower的工做流程和Zab协议。
参考:
《ZooKeeper—Distributed Process Coordination》 by FlavioJunqueira and Benjamin Reed
http://zookeeper.apache.org/doc/trunk/zookeeperOver.html
http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/index.html
《ZooKeeper的一致性算法赏析》https://my.oschina.net/pingpangkuangmo/blog/778927