近段时间在做多平台的配置中心,正好有机会学习了zookeeper,正好可以分享一下zookeeper的基本原理。
说明:部分文字及图片来源于网络,如有涉及侵权,请联络本人删除。
简介
•ZooKeeper是一个分散式的,开放源代码的分散式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要元件。它是一个为分散式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分散式同步、组服务等。
•ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的界面和效能高效、功能稳定的系统提供给使用者。
•简单的说,zookeeper=档案系统+通知机制。
•1)档案系统 :每个子目录项如 NameService 都被称作为znode,和档案系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以储存资料的。
•2)通知机制:客户端注册它关心的目录节点,当目录节点发生变化(资料改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。
原理
•(1)ZooKeeper分为服务器端(Server) 和客户端(Client),客户端可以连线到整个 ZooKeeper服务的任意服务器上(除非 leaderServes 引数被显式设定, leader 不允许接受客户端连线)。
选举过程
•(2)获取观察的事件以及传送心跳。如果这个 TCP 连线中断,客户端将自动尝试连线到另外的 ZooKeeper服务器。客户端第一次连线到 ZooKeeper服务时,接受这个连线的 ZooKeeper服务器会为这个客户端建立一个会话。当这个客户端连线到另外的服务器时,这个会话会被新的服务器重新建立。
•(3)上图中每一个Server代表一个安装Zookeeper服务的机器,即是整个提供Zookeeper服务的丛集(或者是由伪丛集组成);
•(4)组成ZooKeeper服务的服务器必须彼此了解。 它们维护一个内存中的状态影象,以及持久储存中的事务日志和快照, 只要大多数服务器可用,ZooKeeper服务就可用;
•(5)ZooKeeper 启动时,将从例项中选举一个 leader,Leader 负责处理资料更新等操作,一个更新操作成功的标志是当且仅当大多数Server在内存中成功修改资料。每个Server 在内存中储存了一份资料。
•(6)Zookeeper是可以丛集复制的,丛集间通过Zab协议(Zookeeper Atomic Broadcast)来保持资料的一致性;
•(7)Zab协议包含两个阶段:leader election阶段和Atomic Brodcast阶段客户端使用并维护一个 TCP 连线,通过这个连线传送请求、接受响应。
zookeeper角色
1Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协
议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者
崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和leader的状态同步以后
,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。
•ZooKeeper的基本运转流程:
•选举Leader。
•同步资料。
•选举Leader过程中算法有很多,但要达到的选举标准是一致的。
•Leader要具有最高的执行ID,类似root许可权。
•丛集中大多数的机器得到响应并接受选出的Leader。
2为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议 (proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识 leader关系是否改 变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治 时期。低32位用 于递增计数。
•1 Zookeeper leader 选举
• • 半数通过
– 3台机器 挂一台 2>3/2
– 4台机器 挂2台 2!>4/2
• • A提案说,我要选自己,B你同意吗?C你同意吗?B说,我同意选A;C说,我同意选A。(注意,这里超过半数了,其实在现实世界选举已经成功了。
• 还没完。
•
• 接着B提案说,我要选自己,A你同意吗;A说,我已经超半数同意当选,你的提案无效;C说,A已经超半数同意当选,B提案无效。
• 接着C提案说,我要选自己,A你同意吗;A说,我已经超半数同意当选,你的提案无效;B说,A已经超半数同意当选,C的提案无效。
• 选举已经产生了Leader,后面的都是follower,只能服从Leader的命令。而且这里还有个小细节,就是其实谁先启动谁当头。
选举状态
工作状态
•1 Zookeeper 资料同步
•1.在Client向Follwer发出一个写的请求
•2.Follwer把请求传送给Leader
•3.Leader接收到以后开始发起投票并通知Follwer进行投票
•4.Follwer把投票结果传送给Leader
•5.Leader将结果汇总后如果需要写入,则开始写入同时把写入操作通知给Leader,然后commit;
•6.Follwer把请求结果返回给Client
应用场景
•Zookeeper能做什么
•1.命名服务
•2.配置管理
•3.丛集管理
•4.分散式锁
•5.伫列管理
•1 . 命名服务
•命名服务是分散式系统中比较常见的一类场景。命名服务是分散式系统最基本的公共服务之一。在分散式系统中,被命名的实体通常可以是丛集中的机器、提供的服务地址或远端物件等——这些我们都可以统称它们为名字(Name),其中较为常见的就是一些分散式服务框架(如RPC、RMI)中的服务地址列表,通过使用命名服务,客户端应用能够根据指定名字来获取资源的实体、服务地址和提供者的资讯等。
•在zookeeper的档案系统里建立一个目录,即有唯一的path。在我们无法确定上游程式的部署机器时即可与下游程式约定好path,通过path即能互相探索发现。
•3 . 丛集管理
•所谓丛集管理无在乎两点:是否有机器退出和加入、选举master。
对于第一点,所有机器约定在父目录GroupMembers下建立临时目录节点,然后父目录节点的子节点变化讯息。一旦有机器挂掉,该机器与 zookeeper的连线断开,其所建立的临时目录节点被删除,所有其他机器都收到通知:某个兄弟目录被删除,于是,所有人都知道:它上船了。
新机器加入也是类似,所有机器收到通知:新兄弟目录加入,highcount又有了,对于第二点,我们稍微改变一下,所有机器建立临时顺序编号目录节点,每次选取编号最小的机器作为master就好。
•4 . 分散式锁
•有了zookeeper的一致性档案系统,锁的问题变得容易。锁服务可以分为两类,一个是保持独占,另一个是控制时序。
对于第一类,我们将zookeeper上的一个znode看作是一把锁,通过createznode的方式来实现。所有客户端都去建立 /distribute_lock 节点,最终成功建立的那个客户端也即拥有了这把锁。用完删除掉自己建立的distribute_lock 节点就释放出锁。
对于第二类, /distribute_lock 已经预先存在,所有客户端在它下面建立临时顺序编号目录节点,和选master一样,编号最小的获得锁,用完删除,依次方便。
•3 . 伫列管理
•两种型别的伫列:
1、同步伫列,当一个伫列的成员都聚齐时,这个伫列才可用,否则一直等待所有成员到达。
2、伫列按照 FIFO 方式进行入队和出队操作。
第一类,在约定目录下建立临时目录节点,节点数目是否是我们要求的数目。
第二类,和分散式锁服务中的控制时序场景基本原理一致,入列有编号,出列按编号。
实践-配置中心
•程式总是需要配置的,如果程式分散部署在多台机器上,要逐个改变配置就变得困难。现在把这些配置全部放到zookeeper上去,储存在 Zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行,一旦配置资讯发生变化,每个应用程序就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置资讯应用到系统中就好
附录
•https://blog.csdn.net/junchenbb0430/article/details/77583955(zookeeper中的ZAB协议理解)
•https://blog.csdn.net/qiangcuo6087/article/details/79067136 (Zookeeper分散式锁实现)
•https://www.cnblogs.com/LeeScofiled/p/7390937.html(server数量为什么是单数)