1、Zookeeper基础概念
分布式系统
分布式系统特征
CAP理论
BASE理论
一致性协议
Chubby
Zookeeper实现
Zookeeper应用场景
Zookeeper集群角色
Zookeeper集群会话
Zookeeper数据节点(ZNode)
数据版本
事件监听器(Watcher)
ZAB协议(ZK原子广播协议)
集群节点状态及选举
集群选举过程
分布式系统特征
CAP理论
BASE理论
一致性协议
Chubby
Zookeeper实现
Zookeeper应用场景
Zookeeper集群角色
Zookeeper集群会话
Zookeeper数据节点(ZNode)
数据版本
事件监听器(Watcher)
ZAB协议(ZK原子广播协议)
集群节点状态及选举
集群选举过程
分布式系统
Zookpeer是一个分布式协调中间件,主要为分布式系统服务,所以首先要了解分布式系统的痛点在什么地方,才能更好的了解Zookpeer的真正价值和意义;
分布式系统,比如分布式文件系统、MySQL主从等,只要工作不是在同一个节点上的系统和应用,我们都可以称之为分布式系统,总结来说分布式系统其实是一个硬件或软件组件分布在网络中的不同计算机之上而且彼此间仅通过消息传递进行通信和协作的系统;
分布式系统特征
一般来讲,分布式系统通常有几个特征,第一分布性,他们都分布在不同计算机之上,第二并发性,他们都需要同时向外提供服务,第三网络,网络是不可靠的,因此出现通信异常的现象也的必然会发生的;
由于上面三个点,它所面临的典型问题,第一通信异常,通信异常,第二网络分区但是通信也并不一定会产生网络分区,只不过网络分区是通信异常的一种特殊表现,而且对整个分布式系统也是最大的一种特殊表现,第三三态,整个系统有可能在这三种状态之间进行转换,成功、失败、超时,第四节点故障,对于分布式系统来讲,主机多了那么出现故障的概率也就大了,那节点也几乎必然会发生故障的;
这就是我们分布式系统当中所面临的典型问题,因此为了解决分布式系统所解决的问题,于是我们就有了所谓的CAP理论,CAP理论其实就是为了解决上的问题,而衍生的一个理论论点;
CAP理论
大概是2000年7月份加州大学伯克利分校的Eric Brewer在ACM PODC这个杂志上首次提出这么一个CAP理论基础猜想,两年之后大概是2002来自于麻省理工学院的Seth Gilbert和Nancy Lynch从理论上证明了的的确确是存在这么一个定理的,因此使得其后来直接成为了一个定理,被任何分布式系统设计者所广泛采用,而且在设计时基本上也遵循次定理;
C:一致性;
A:可用性;
P:网络分区容错性;
其实任何一个分布式系统最多只能满足CAP中至多两个,最多只能同时满足两项,由于分布式系统P(网络分区容错性)我们必须得容忍它,比如得保证它存在,因此我们只能从CA之间进行选择,所以这样带来的结果要么是CP要么是AP,而CP主要考虑,一致性和容错性,AP主要考虑可用性和容错性;
但是我们只保证可用,而放弃一致性的话,其实数据的没有什么价值和意义的,因此一个没有一致性的分布式系统没有任何价值,所以即便我们采用AP这种法则,通常我们应该最终要保证C能实现,只不过是在一个特定的时间窗口以后,再给予满足,所以后来基于这种方式进行权衡就有了BASE理论;
BASE理论
BA:基本可用,指的是分步系统在出现不可预知的故障时,允许损失部分可用性,所以叫基本可用;
S:软状态,所谓软状态指的是,允许系统状态存在中间状态,而且该状态的存在不会影响整体可用性,也就是说允许系统在不同的节点的数据副本之间窗口在保证数据同步时,允许接受一定程度的时间延迟,在一个时间窗口内用户从不同节点所获得的数据可以是不同的;
E:最终一致性,系统中的所有副本,经过S的这个时间窗口以后,最终必须能达到数据一致性的状态;
一致性协议
一般而言,在同一个分布式系统中进行架构设计的过程,通常而言,不得不在可用性和一致性之间来回进行权衡,于是就产生了一堆的一致性协议,就是为了保证分布式系统的各种一致性有很多,比如2 Phase-Commit两段式提交、3 Phase-Commit三段式提交、Paxis帕克索斯协议,这几种方式就是来保证分布式系统中的各种一致性的各种协议;
2 Phase-Commit:整个数据提交的过程,要分成多步进行,如果有多个节点进行参与的话,会把整个提交过程分为两步进行,第一步是参与的各方做出提交准备, 当所有参与方的请求都达到了,然后才能进入第二步,第一阶段都准备齐备之后,开始提交数据,短板是第一阶段需要等到所有的参与方进行准备,如果有一个没有做出提交准备,那么就会带来消息的大量阻塞,而且这里还会面临单点问题,脑裂问题等;
3 Phase-Commit:正因为2 Phase-Commit存在的问题,后来就改进了它成为了3 Phase-Commit,第一步先发出请求,第二步进行预提交,第三步才是真正的提交数据,依然是需要多方进行参与,但是第一步会判断整个集群当中有哪些节点能进行提交,哪些节点可以参与请求提交过程,只有这些参与者才会被阻塞,因此比起来2 Phase-Commit而言,它降低了阻塞影响到的范围,但是这种方式也带来了数据可能会发生不一致的可能性;
Paxos:目前为止Paxos是唯一公认的在解决分布式系统一致性问题最有效的方法之一,现今也有很多分布式协议是基于Paxos这么一个协议来实现的,Zookpeeper也并不是Paxos的实现,把Paxos的实现思路做了一些变更,因为Paxos的算法实现起来非常的难,因此,后来为了能够把这种理论用工程的方式给它加以实践出来,Google研发了一个项目Chubby;
Chubby:Google的Chubby是一个著名的,分布式锁服务,Google的很多项目,比如GFS、BigTable等系统,都是用Chubby来实现所谓的分布式锁服务的相关问题的,Chubby的主要几个作用第一分布式写作,第二元数据存储,第三Master选举等一系列与分布式锁服务的相关的问题;
Chubby
Chubby能够为松耦合的分布式系统提供一个高耦合的分布式锁服务,分布式锁服务的目的是为了能够让它的客户端能够进行同步各客户端,各客户端能够通过Chubby来同步自己的操作;
在早期多个节点之间的进程彼此之间进行协调,那么就需要在他们彼此之间进行通讯了,这会面临很多问题,比如其中一个节点挂了那如何进行协调,其他节点又怎么确定是这个节点挂了还是自己网络问题呢,都面临着各种问题,在这种场景当中是非常麻烦的;
因此这三个节点之间进行协调就不在彼此之间进行通讯了,而是都与一个公共存储服务进行通信,当然我们称之为存储,它其实也的确能够提供一定意义上的存储功能,但更多的是这个服务给我们提供的其他的功能,比如连接到这个服务的分布式节点程序都能够把自己的状态随时按固定的周期同步到存储服务上来保存为一个数据节点,一旦当这个数据节点对应的分布式节点挂了,这个数据节点也相应的移除,其他节点连到存储服务上找不到自己所关注的同一个分布式集群的服务节点相关数据就认为这个节点不存在了,另外这个存储服务在内部的协议书还支持所谓的Master选举功能,并且Chubby这个节点也是支持使用自己id协议完成高可用的;
Zookeeper实现
Google的Chubby就是这个公共的分布式协作存储组件,既然Google的GFS、BigTable都被山寨了,山寨成了HDFS和HBASE,但是HDFS和HBASE也需要协作服务,于是又山寨了Chubby就是我们的Zookeeper,因为很多面临这种分布式协作的程序就开始纷纷利用了这种机制,用Zookeeper来实现分布式系统的协作,所以站在这么一个角度来讲Zookeeper事实就是一个开源的分布式协作服务,由知名互联网公司Yahoo创建,它是Chubby的开源实现,换句话讲Zookeeper其实是一个典型的分布式数据一致性解决方案,各种各样的分布式应用程序可以基于它去实现数据发布/订阅、负载均衡、名称服务、分布式协调/通知以、集群管理、Master选举、分布式锁和分布式队列;
其实企业级的很多分布式应用都是基于Zookeeper来实现的,非但如此Zookeeper还有一个非常奇葩的用法,我们可以把一个服务的配置文件放在Zookeeper中,万一服务挂了,再启一个服务利用Zookeeper来装载自己的配置文件也可以做到,有很多企业会把这些关键性的服务的配置文件,直接放在Zookeeper里面,还能做到,当需要更新配置文件时,只需要更新Zookeeper上的配置即可然后Zookeeper可以直接通知订阅了这个配置文件的各节点重载服务;
Zookeeper应用场景
Zookeeper的典型应用场景如下有;
发布/订阅:
负载均衡:负载均衡,可以在非常独特的场景下进行负载均衡,当客户端请求访问某一服务时,它不会直接去找服务,而是直接去找Zookeeper,那么Zookeeper就会告诉它服务有三个,Zookeeper就会基于轮询的方式随机挑选一个给客户端请求;
命名服务:每个主机是怎么命令的;
分布式协调/通知:
集群管理:
Master选举:
分布式锁:
Zookeeper集群角色
Zookeeper它本身也可以组成集群,多数企业也的确都是使用的集群模式,一般都是三节点,在Zookeeper自己的集群当中所应该具有的角色有如下几个,Leader(主节点),Follower(从节点),Oberserver(观察员);
这里的Ledaer就是通过Follower和Oberserver选举产生的,它是整个集群负责写操作的节点,既然Zookeeper要存储数据,又有多个节点,而且还需要保证每一个节点数据一致,所以它必须要基于主从模式进行,也就意味着Zookeeper Cluster依然是拥有不对等的地位的,Follower和Oberserver都是用来提供读服务的,他们都是从节点,所不同的是,Oberserver也可以参与选举过程,但是不能够被选举,所以它是不会成为Master的,其他的节点当Leader挂了,会重新发起一轮选举,那么此时就有一个Follower会成为Leader,当老的Leader重新激活上线,它就变成了Follower;
Leader(主节点):选举产生,它负责读和写的服务;
Follower(从节点):可以参与选举也可以被选举,当它没有成为Leader之前提供读服务;
Oberserver(观察员):可以参与选举,但是不能被选举,供读服务;
Zookeeper集群会话
分布式系统是利用Zookeeper来进行协调的,所以这些分布式系统本身也可能是一个集群,那这些节点正是利用Zookeeper所提供的服务来彼此之间互知的,比如分布式系统中的某一个节点想知道当前集群中有几个存活节点,那么它就可以到Zookeeper上去请求某一个数据分支;
Zookeeper的数据管理模型是倒置树状的数据结构,那么就可以去Zookeeper服务上请求一个树状的文件系统,一个分布式文件系统可以注册使用一个子节点,也就以为着在这个子节点之上每一个分布式服务都可以注册一个叶子节点用来保存自己的状态,在线这个叶子节点就存在,不在线就不存在,所以这三台主机脸上Zookeeper以后可以基于自己所关注的这个Zookeeper节点上的信息,查看一下有几个叶子节点,就知道当前这个集群中有多少个主机依然在线;
并且这每一台主机都需要随时更新自己的状态信息的,主机连到Zookeeper上之后这么一个会话将始终存在,所以我们的Zookeeper是一个C/S模型的程序,所以每一个Zookeeper的客户端,也就是分布式系统的各个节点服务,这个分布式服务和Zookeeper之间会建立一个一直存在的连接,这个连接只有在客户端不再参与分布式系统,或者客户端出现故障宕机才会关掉的,在Zookeeper当中,分布式系统想要进行协调,它必须都要与Zookeeper服务器建立一个持久会话,并且,它们也会通过这么一个会话不断更新自己在Zookeeper当中关于自己节点状态的相关数据信息,比如每隔3秒钟更新一次,它会每隔3秒更新一次自己的时间戳,其他节点也正式看到了这么一个节点信息的更新才知道这个节点是正常存活的,它是通过这种方式来进行协调的;
所以会话是至关重要的,是Zookeeper与分布式服务之间建立的一个PCP长连接,从连接建立开始,其客户端会话就一直存在,直到我们的节点不再参与分布式系统,或者故障宕机才会关闭,当然如果客户端与Zookeeper之间的会话因为网络故障而导致无法连接上的,我们也可以设定一个sessionTimeout会话超时时常;
Zookeeper数据节点(ZNode)
在Zookeeper当中所谓的数据节点指的是,在这个倒置的树状结构上的分支节点,或者叶子节点,都叫做数据节点,也称之为Zookeeper数据模型中的数据单元,Zookeeper的数据都存储在内存中,数据模型为树状结构,我们将其称为ZNode Tree,每个ZNode都会保存自己的数据于内存中,不过需要注意的是,ZNode节点有两类,一类的持久节点,一类是临时节点;
持久节点:一直存在,只有通过显示删除的方式才能移除;
临时节点:会话终止就会自动消失;
数据版本
每个ZNode,Zookeeper都会为其维护一个Stat的数据结构,它主要记录了当前ZNode的三个数据版本,第一是version当前版本,第二是cversion当前ZNode子节点的版本,第三aversion当前ZNode的访问控制列表的版本ACL;
cversion对于当前ZNode虽然自己的版本是2,但是它的子节点有可能会变来变去,所以它通过一个节点就能知道它的子节点变化了多少次了;
aversion当前ZNode的ACL的版本, 一个Zookeeper集群是公共的,N个分布式系统都会使用一个Zookeeper集群来协调自己的服务,所以他们彼此之间必须要隔离出来,那么隔离就得需要通过权限控制来隔离,所以Zookeeper是使用ACL策略来实现权限控制的,比如Create、Read、Write、Delete、Admin,因此ACL权限发生了变化,也应该明确说明当前ACL是处于第几版的授权信息了;
事件监听器(Watcher)
如果这些在同一个分布式系统中,通过我们的Zookeeper选举出了主节点,万一主节点挂了,其他节点还一无所知,显然不行,这每一台主机都可以通过注册去监听其他节点保存的关于它自己的存活状态的信息,假设有A节点和B节点,A节点需要监听B节点的状态信息,那么A就需要注册一个监听器,监听B节点的数据状态信息,一旦B节点发生变化,事件监听器能够立即将变化通知给注册监听的A节点;
ZAB协议(ZK原子广播协议)
对于Zookeeper来讲,所有的分布式节点,都可以基于Zookeeper自己的这些系统来完成选举、协调、发布订阅等功能,而Zookeeper实现这些功能的机制是靠Zookeeper的专用的ZAB协议来事先的,是通过ZAB协议完成来各节点参与之间所谓的Leader选举等功能,所以ZAB协议是Zookeeper的核心,ZAB的全称是Zookeeper Atomic Broadcast,Zookeeper的原子广播协议,它主要被设计用来支持崩溃恢复机制,用于在Leader进程崩溃时进行重新选举出新的Leader,并且还要保证数据完整性和一致性;
对于Zookeeper自己的集群来讲,它也需要一个Leader、Follower和Oberserver,因此在Zookeeper的集群当中,所有事物的请求当中都是由Leader来处理的,其它服务器,比如Follower或Oberserver只提供读服务,所以写请求一样的,只由Leader来进行,当一个节点要去进行写数据时,这个写操作是发给Leader的,Leader会把这个修改的请求转为一个题案,向当前Zookeeper集群进行广播,意思是Leader现在要修改数据,询问各Follower是否同意,只要法定票数过半之后Leader就开始把数据直接写进内存中去了;
集群节点状态及选举
对于我们ZAB协议中存在四种状态,第一Looking,表示我们每一个节点刚开始启动时,它应该先去找Leader,系统刚启动或者系统崩溃以后,正处于的选举过程,我们就称之为Looking的过程,第二个Following,Follower节点所处的状态就是Following状态,第三Observer节点状态是Observing,第四Leading,Leader所属的状态就是Leading状态,因此每一个节点都有可能会在这三种状态中转换;
所以说Zookeeper启动时,所有节点默认都处于Looking状态,这个时候整个集群会尝试选举出一个Leader,而后被选举出来的Leader将会被切换为Looking,其它的非Observer将会切换为Following状态,然后Observer节点则就会一直处于Observing状态,当节点发现集群中已经选举出来Leader,那么其他节点或者后来的节点就自动从Looking转为Following状态,而且尝试与Leadr保持同步,从Leader上把所有数据都同步过来,当Follower节点与Leader节点失去联系时,Follower节点会再次切换到Following状态,并开始开启新一轮选举,所以说整个集群中的每一个节点将始终在这三个状态中进行转换;
选举出Leader节点之后,ZAB协议将进入原子广播节点,这个时候Leader和那些与自己同步的每个Follower节点会创建一个操作序列,这些Follower有可能和Leader的数据不一样,所以这个时候,Leader需要将自己的这个数据打包,同步给每一个Follower节点和Observer节点,而后Leader节点还必须与Follower节点使用心跳检测机制,去检测每一个Follower节点是否处于正常状态的,这种检测机制就可以想象成Follower在集群中某个地方不断的去更新自己的数据版本或者是时间戳,如果一直在更新Leader就认为他们是正常的,否则一旦在一个超出指定时间当中一个Follower没再更新自己的心跳信息,那么随后这个Follower就被理解为失去连接状态;
集群选举过程
整个ZAB当中的选举过程大体上分为四个阶段,分别是选举(election)、发现(discovery)、同步(sync)、广播(broadcast);