Zookeeper工作原理
Posted swimming_in_it_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Zookeeper工作原理相关的知识,希望对你有一定的参考价值。
一 Zookeeper是什么
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供给用户,主要为了解决分布式架构下数据一致性问题,典型的应用场景有分布式配置中心、分布式注册中心、分布式锁、分布式队列、集群选举、分布式屏障、发布/订阅等场景。简单说zookeeper=文件系统+通知机制。
1,Zk的文件系统
每个子目录项如 NameService 都被称作为znode,和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的。
- 持久化目录节点:客户端与zookeeper断开连接后,该节点依旧存在,只要不手动删除该节点,他将永远存在。
- 持久化顺序编号目录节点:客户端与zookeeper断开连接后,该节点依旧存在,只是zookeeper给该节点名称进行顺序编号。
- 临时目录节点:客户端与zookeeper断开连接后,该节点被删除。
- 临时顺序编号目录节点:客户端与zookeeper断开连接后,该节点被删除,只是zookeeper给该节点名称进行顺序编号。
2,zk的通知机制
客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。监听事件如下:
1、None:连接建立事件
2、NodeCreated:节点创建
3、NodeDeleted:节点删除
4、NodeDataChanged:节点数据变化
5、NodeChildrenChanged:子节点列表变化
6、DataWatchRemoved:节点监听被移除
7、ChildWatchRemoved:子节点监听被移除
3,zk的角色
- 领导者(leader),负责进行投票的发起和决议,更新系统状态
- 学习者(learner),包括跟随者(follower)和观察者(observer),follower用于接受客户端请求并想客户端返回结果,在选主过程中参与投票
- Observer可以接受客户端连接,将写请求转发给leader,但observer不参加投票过程,只同步leader的状态,observer的目的是为了扩展系统,提高读取速度。zoo.cfg中添加peerType=Observer,这表示这个server以observer角色运行,即不参与投票。再在所有 server的配置文件中,修改server.X配置项,在那些observer的节点上加上:observer后缀。例如,server.1对应的server要作为observer:Server.1=IP:2181:3181:observer
这样配置后,ZooKeeper集群中的所有服务器节点都知道哪些节点扮演的是observer角色。 - 客户端(client),请求发起方
4,CAP理论
zookeeper:满足数据的最终一致性,但是在leader选举过程中不可用。
Eureka:在任何时间都可用,但是可能有数据不一致的情况.
- C是一致性,Consistency,就是各个节点保存的数据都是最新的。
- A是Availability, 可用性,每次请求都可以获得响应,但是没法保证是最新的响应。
- P是分区容错性(Partition tolerance),就是每个节点可能都存在于不同的子网络,也就是不同的分区,不同分区之间的通信总是有可能发生故障的,或者总是有可能存在一些节点挂了的情况。
可以认为P总是成立的,C和A是无法同时做到。所以一般对于数据一致性要求特别高的业务,例如支付,交易相关的业务,就是会优先保证一致性C和分区容错性P,就是保证数据一致性,例如让所有子节点都收到更新后才算提交成功,就像mysql主从同步中的全同步模式一样。普通的业务是优先保证可用性A和分区容错性P,比如在MySQL主从同步时,默认就是异步的方式,我们执行一条更新SQL,只需要主节点更新成功就行就对事务进行提交,不需要等待从节点更新数据成功,主节点会异步把SQL发送给从节点。
二 zk的工作流程
Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和leader的状态同步以后 ,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。
为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid) 来标识事务。所有的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。
每个Server在工作过程中有三种状态:
- LOOKING:当前Server不知道leader是谁,正在搜寻
- LEADING:当前Server即为选举出来的leader
- FOLLOWING:leader已经选举出来,当前Server与之同步
1,zk的选主流程
当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的 Server都恢复到一个正确的状态。Zk的选举算法有两种:一种是基于basic paxos实现的,另外一种是基于fast paxos算法实现的。系统默认的选举算法为fast paxos。
1)basic paxos流程:
- 选举线程由当前Server发起,其主要功能是对投票结果进行统计,并推选出Leader
- 选举线程首先向所有的server发次一次询问(包括自己)
- 选举线程收到回复后,验证是否是自己发起的询问(验证zxid),然后获取对方的id(myId),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(zxid和myid),并将这些信息存储到当次选举的投票记录中。
- 收到所有的server回复后,就计算出zxid最大的server,并将这个Server相关的信息设置成下次要投票成leader的server。
- 线程将当前最大zxid的server设置成推荐leader时,如果获得n/2+1的server同意,则zxid最大的server称为leader,然后将根据获胜的server相关的信息来设置自己的状态,否则继续当前流程,直到leader选出。
通过流程分析我们可以得出:要使Leader获得多数Server的支持,则Server总数必须是奇数2n+1,且存活的Server的数目不得少于n+1。
每个Server启动后都会重复以上流程。在恢复模式下,如果是刚从崩溃状态恢复的或者刚启动的server还会从磁盘快照中恢复数据和会话信息,zk会记录事务日志并定期进行快照,方便在恢复时进行状态恢复。选主的具体流程图如下所示:
2)fast paxos流程
是在选举过程中,某Server首先向所有Server提议自己要成为leader,当其它Server收到提议以后,解决epoch和 zxid的冲突,并接受对方的提议,然后向对方发送接受提议完成的消息,重复这个流程,最后一定能选举出Leader。其流程图如下所示:
如果还不明白可以参考:
https://blog.csdn.net/qq_35128600/article/details/104798113
2,zk的同步流程
选完leader以后,zk就进入状态同步过程。
- leader等待server连接;
- Follower连接leader,将最大的zxid发送给leader;
- Leader根据follower的zxid确定同步点;
- 完成同步后通知follower 已经成为uptodate状态;
- Follower收到uptodate消息后,又可以重新接受client的请求进行服务了。
流程图如下所示:
3,zk的工作流程
ZooKeeper集群中的每个server都能为客户端提供读、写服务。对于客户端的读请求,server会直接从它本地的内存数据库中取出数据返回给客户端,这个过程不涉及其它任何操作,也不会联系leader。对于客户端的写请求,因为写操作会修改znode的数据、状态,所以必须要在ZooKeeper集群中进行协调。处理过程如下:
如图所示:
- 收到写请求的那个server,首先将写请求发送给leader。
- leader收到来自follower(或observer)的写请求后,首先计算这次写操作之后的状态,然后将这个写请求转换成带有各种状态的事务(如版本号、zxid等等)。
- leader将这个事务以提议的方式广播出去(即发送proposal)。
- 所有follower收到proposal后,对这个提议进行投票,投票完成后返回ack给leader。follower的投票只有两种方式:(1)确认这次提议表示同意;(2)丢弃这次提议表示不同意。
- leader收集投票结果,只要投票数量达到了大多数的要求(例如,5个节点的集群,3个或3个以上的节点才算大多数),这次提议就通过。
- 提议通过后,leader向所有server发送一个提交通知。
- 所有节点将这次事务写入事务日志,并进行提交。
- 提交后,收到写请求的那个server向客户端返回成功信息。
上面只是简单的介绍了下zk的写流程,实际过程中,leader和foller还有好多其他的功能,具体如下。
1.Leader的工作流程
Leader的主要功能是:恢复数据和维持与foller的心跳,并接收foller的请求消息类型。leader接收的消息类型主要有
- PING消息:指的是foller的心跳信息。
- REQUEST消息:foller发送的提议信息,包括写请求和同步数据请求
- ACK消息:foller对于提议信息的恢复,超过半数的foller同意,则该commit该提议。
- REVALIDATE消息:是用来延长session的有效时间。
Leader的工作流程简图如下所示,在实际实现中,流程要比下图复杂得多,启动了三个线程来实现功能。
2.foller的工作流程
Follower主要有四个功能:
- 向Leader发送请求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息)
- 接收Leader消息并进行处理;
- 接收Client的请求,如果为写请求,发送给Leader进行投票;
- 返回Client结果。
Follower的消息循环处理如下几种来自Leader的消息:
- PING消息: 心跳消息;
- PROPOSAL消息:Leader发起的提案,要求Follower投票;
- COMMIT消息:服务器端最新一次提案的信息;
- UPTODATE消息:表明同步完成;
- REVALIDATE消息:根据Leader的REVALIDATE结果,关闭待revalidate的session还是允许其接受消息;
- SYNC消息:返回SYNC结果到客户端,这个消息最初由客户端发起,用来强制得到最新的更新。
Follower的工作流程简图如下所示,在实际实现中,Follower是通过5个线程来实现功能的
三 zk的常见应用场景
1,zk的命名服务
命名服务是指通过指定的名字来获取资源或者服务的地址,提供者的信息。利用Zookeeper很容易创建一个全局的路径,而这个路径就可以作为一个名字,它可以指向集群中的集群,提供的服务的地址,远程对象等。简单来说使用Zookeeper做命名服务就是用路径作为名字,路径上的数据就是其名字指向的实体。
例如:Dubbo中使用ZooKeeper来作为其命名服务,维护全局的服务地址列表。在Dubbo实现中:
- 服务提供者在启动的时候,向ZK上的指定节点/dubbo/$serviceName/providers目录下写入自己的URL地址,这个操作就完成了服务的发布。
- 服务消费者启动的时候,订阅/dubbo/serviceName/providers目录下的提供者URL地址, 并向/dubbo/serviceName /consumers目录下写入自己的URL地址。
2,zk的配置管理
程序总是需要配置的,如果程序分散部署在多台机器上,要逐个改变配置就变得困难。现在把这些配置全部放到zookeeper上去,保存在 Zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中就好
3,zk的注册中心
所谓集群管理无在乎两点:是否有机器退出和加入、选举master。
- 对于第一点,所有机器约定在父目录GroupMembers下创建临时目录节点,然后监听父目录节点的子节点变化消息。一旦有机器挂掉,该机器与 zookeeper的连接断开,其所创建的临时目录节点被删除,所有其他机器都收到通知:某个兄弟目录被删除,于是,所有人都知道:它上船了。新机器加入也是类似,所有机器收到通知:新兄弟目录加入,highcount又有了
- 对于第二点,我们稍微改变一下,所有机器创建临时顺序编号目录节点,每次选取编号最小的机器作为master就好。
4,zk的分布式锁
有了zookeeper的一致性文件系统,锁的问题变得容易。锁服务可以分为两类,一个是保持独占,另一个是控制时序。
- 对于第一类,我们将zookeeper上的一个znode看作是一把锁,通过createznode的方式来实现。所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁。用完删除掉自己创建的distribute_lock 节点就释放出锁。
- 对于第二类, /distribute_lock 已经预先存在,所有客户端在它下面创建临时顺序编号目录节点,和选master一样,编号最小的获得锁,用完删除,依次方便。
5,zk的队列管理
两种类型的队列:
- 同步队列,当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达。在约定目录下创建临时目录节点,监听节点数目是否是我们要求的数目。
- 队列按照 FIFO 方式进行入队和出队操作。和分布式锁服务中的控制时序场景基本原理一致,入列有编号,出列按编号。
四 zk的常见问题
1,zk的节点信息
通过stat命令来查看主要信息,其中信息有:
1、cZxid:创建znode的事务id(Zxid的值)。
2、mZxid:最后修改znode的事务id。
3、pZxid:最后添加或删除子节点的事务id(子节点列表发生变化才会发生改变)。
4、ctime:znode创建时间。
5、mtime:znode最近修改时间。
6、dataVersion:znode的当前数据版本。
7、cversion:znode的子节点结果集版本(一个节点的子节点增加、删除都会影响这个版本)。
8、aclVersion:表示对此znode的acl版本。
9、ephemeralOwner:znode是临时znode时,表示znode所有者的sessionid,如果znode不是临时节点,则该字段设置为零。
10、dataLength:znode数据字段的长度。
2,zookeeper创建节点
1、创建持久节点:create /节点名称
2、创建持久顺序节点:create -s /节点名称
3、创建临时节点:create -e /节点名称
4、创建临时顺序节点:create -e -s /节点名称
5、监听节点:get -w /节点名称
3,zookeeper的权限控制
zookeeper有ACL( Access Control List )权限控制,可以控制节点的读写操作,保证数据的安全性。
ACL(Access Control List),分别由权限模式,授权对象和权限信息组成
1)权限模式:
- 范围验证:zookeeper可以通过对一个ip或者一段ip进行授权。
- 口令验证:用户名密码方式验证
2)授权对象: 就是把权限授予给谁,如果是范围验证方式,那么授权对象就是ip地址,如果是口令验证,授权对象就是用户名。
3)权限信息:
- 数据节点(c:create)创建权限,授予权限的对象可以在数据节点下创建子节点。
- 数据节点(w:wirte)更新权限,授予权限的对象可以更新该数据节点
- 数据节点(r:read)读取权限,授予权限的对象可以读取该节点的内容以及子节点的列表信息。
- 数据节点(d:delete)删除权限,授予权限的对象可以删除该数据节点的子节点。
- 数据节点(a:admin)管理者权限,授予权限的对象可以对该数据节点体进行ACL权限设置。
可以通过getAcl来获取某个节点的权限信息,通过setAcl来设置某个节点的权限信息。
4,zookeeper的数据持久化
zookeeper和redis很像,数据都是在内存中的,持久化也是两种方式,一种是记录事务日志,一种是快照方式。
记录事务日志磁盘会进行IO操作,事务日志的不断增多会触发磁盘为文件开辟新的磁盘块,所以为了提升磁盘的效率,可以在创建文件的时候
就向操作系统申请一块大一点的磁盘块,通过参数zookeeper.preAllocSize配置。事务日志的存放地址通过zoo.cfg配置文件中的dataDir来指定。
参考文献:
https://blog.csdn.net/u014374173/article/details/105173043
https://blog.csdn.net/weixin_38612401/article/details/125216821
leader选举:
https://blog.csdn.net/qq_35128600/article/details/104798113
初识zookeeper--工作原理
Zookeeper工作原理简介
实战:企业中Zookeeper的工作范畴
ZooKeeper是Hadoop Ecosystem中非常重要的组件,它的主要功能是为分布式系统提供一致性协调(Coordination)服务,与之对应的Google的类似服务叫Chubby。今天先介绍ZooKeeper的基本原理。官网:http://zookeeper.apache.org/
官网翻译:Apache ZooKeeper是努力发展和维持一个开放源码的高度可靠的分布式协调系统。
ZooKeeper是一个集中式服务维护配置信息,命名、提供分布式同步,并提供集团服务的系统。
1.系统模型及其特点:
1.最终一致性:client不论连接到哪个Server,展示给它都是同一个视图,这是zookeeper最重要的性能。
2 .可靠性:具有简单、健壮、良好的性能,如果消息m被到一台服务器接受,那么它将被所有的服务器接受。
3 .实时性:Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网络延时等原因,Zookeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。
4.原子性:更新只能成功或者失败,没有中间状态。
A想要从自己的帐户中转1000块钱到B的帐户里。那个从A开始转帐,到转帐结束的这一个过程,称之为一个事务。在这个事务里,要做如下操作:
1. 从A的帐户中减去1000块钱。如果A的帐户原来有3000块钱,现在就变成2000块钱了。
2. 在B的帐户里加1000块钱。如果B的帐户如果原来有2000块钱,现在则变成3000块钱了。
如果在A的帐户已经减去了1000块钱的时候,忽然发生了意外,比如停电什么的,导致转帐事务意外终止了,而此时B的帐户里还没有增加1000块钱。那么,我们称这个操作失败了,要进行回滚。回滚就是回到事务开始之前的状态,也就是回到A的帐户还没减1000块的状态,B的帐户的原来的状态。此时A的帐户仍然有3000块,B的帐户仍然有2000块。
我们把这种要么一起成功(A帐户成功减少1000,同时B帐户成功增加1000),要么一起失败(A帐户回到原来状态,B帐户也回到原来状态)的操作叫原子性操作。
如果把一个事务可看作是一个程序,它要么完整的被执行,要么完全不执行。这种特性就叫原子性。
2.数据模型:
· ZooKeeper数据模型的结构与Unix文件系统很类似,整体上可以看作是一棵树,每个节点称做一个ZNode。每个ZNode都可以通过其路径唯一标识,比如上图中第三层的第一个ZNode, 它的路径是/app1/c1。在每个ZNode上可存储少量数据(默认是1M,可以通过配置修改, 通常不建议在ZNode上存储大量的数据),这个特性非常有用,在后面的典型应用场景中会介绍到。另外,每个ZNode上还存储了其Acl信息,这里需要注意,虽说ZNode的树形结构跟Unix文件系统很类似,但是其Acl与Unix文件系统是完全不同的,每个ZNode的Acl的独立的,子结点不会继承父结点的
Access Control List,ACL是路由器和交换机接口的指令列表,用来控制端口进出的数据包,IOS所提供的一种访问控制技术。
ZNode根据其本身的特性,可以分为下面两类:
· Regular ZNode: 常规型ZNode, 用户需要显式的创建、删除
· Ephemeral ZNode: 临时型ZNode,用户创建它之后,可以显式的删除,也可以在创建它的Session结束后,由ZooKeeper Server自动删除
ZNode还有一个Sequential的特性,如果创建的时候指定的话,该ZNode的名字后面会自动Append一个不断增加的SequenceNo。[skwenl] 按次序的,相继的
2.2 Session Session:一段时间。在计算机中,尤其是在网络应用中,称为“会话控制”
Client与ZooKeeper之间的通信,需要创建一个Session,这个Session会有一个超时时间。因为ZooKeeper集群会把Client的Session信息持久化,所以在Session没超时之前,Client与ZooKeeper Server的连接可以在各个ZooKeeper Server之间透明地移动。
在实际的应用中,如果Client与Server之间的通信足够频繁,Session的维护就不需要其它额外的消息了。否则,ZooKeeper Client会每t/3 ms发一次心跳给Server,如果Client 2t/3 ms没收到来自Server的心跳回应,就会换到一个新的ZooKeeper Server上。这里t是用户配置的Session的超时时间。
2.3 Watcher
ZooKeeper支持一种Watch操作,Client可以在某个ZNode上设置一个Watcher,来Watch该ZNode上的变化。如果该ZNode上有相应的变化,就会触发这个Watcher,把相应的事件通知给设置Watcher的Client。需要注意的是,ZooKeeper中的Watcher是一次性的,即触发一次就会被取消,如果想继续Watch的话,需要客户端重新设置Watcher。这个跟epoll里的oneshot模式有点类似
小结:
系统模型及其特点的介绍
数据模型
本文出自 “目标:印度” 博客,请务必保留此出处http://shunzi115.blog.51cto.com/5184443/1914023
以上是关于Zookeeper工作原理的主要内容,如果未能解决你的问题,请参考以下文章