Zookeeper主要用于分布式系统中,为了提供高可用的服务,作用主要包括两点:
Zookeeper中的角色:
Leader:领导者,负责进行投票的发起和决议,更新系统状态
Learner:
Follower:追随者接收客户请求并向客户端返回结果,在选主过程中进行投票
Observer:观察者不参与投票,仅同步leader的状态。目的是为了扩展系统,提高读取速度。
Client:请求发起方
Zookeeper中节点在工作过程中有三种状态:
LOOKING:当前Server不知道leader是谁,正在搜寻
LEADING:当前Server即为选举出来的leader
FOLLOWING:leader已经选举出来,当前Server与之同步
Zookeeper与客户端
zookeeper与客户端
整体流程如下:
1.在客户端向Follwer发出一个写的请求
2.Follwer把请求发送给负责人
3.Leader接收到以后开始发起投票并通知Follwer进行投票
4.Follwer把投票结果发送给负责人
5.Leader将结果汇总后如果需要写入,则开始写入同时把写入操作通知给负责人,然后提交;
6.Follwer把请求结果返回给客户端
基于消息传递通信模型的分布式系统,不可避免的会发生以下错误:进程可能会慢,被杀死或者重启,消息可能会延迟,丢失,重复,在基础Paxos场景中,先不考虑可能出现消息篡改即拜占庭错误(Byzantine failure,即虽然有可能一个消息被传递了两次,但是绝对不会出现错误的消息)的情况.Paxos算法解决的问题是在一个可能发生上述异常的分布式系统中如何就某个值达成一致,保证不论发生以上任何异常,都不会破坏决议一致性。
Paxos算法使用一个希腊故事来描述,在Paxos中,存在三种角色,分别为
下面更精确的定义Paxos要解决的问题:
1,决议(价值)只有在提议者提出后才能被批准
2,在一次Paxos算法的执行实例中,只批准(选择)一个值
3,学习者只能获得被批准(选择)的价值
ZooKeeper的选举算法有两种:一种是基于Basic Paxos(Google Chubby采用)实现的,另外一种是基于Fast Paxos(ZooKeeper采用)算法实现的。系统默认的选举算法为Fast Paxos。并且ZooKeeper在3.4 .0版本后只保留了FastLeaderElection算法。
ZooKeeper的核心是原子广播,这个机制保证了各个服务器之间的同步。实现这个机制的协议叫做ZAB协议(Zookeeper Atomic BrodCast).ZAB协议有两种模式,它们分别是崩溃恢复模式(选主)和原子广播模式(同步)。
1,当服务启动或者在领导者崩溃后,ZAB就进入了恢复模式,当领导者被选举出来,且大多数服务器完成了和领导的状态同步以后,恢复模式就结束了。状态同步保证了领导者和跟随者之间具有相同的系统状态。
2,当ZooKeeper集群选举出领导同步完状态退出恢复模式之后,便进入了原子广播模式。所有的写请求都被转发给领导者,再由领导者更新提议广播给追随者
为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(提议)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是时代用来标识领导关系是否改变,每次一个领导被选出来,它都会有一个新的时代,标识当前属于那个领导者的统治时期。低32位用于递增计数。
以一个简单的例子来说明整个选举的过程:假设有五台服务器组成的zookeeper集群,它们的serverid从1-5,同时它们都是最新启动的,也就是没有历史数据,在存放数据量这一点上,都是一样的。假设这些服务器依序启动,来看看会发生什么
1,服务器1启动,此时只有它一台服务器启动了,它发出去的报没有任何响应,所以它的选举状态一直是看状态
2,服务器2启动,它与最开始启动的服务器1进行通信,互相交换自己的选举结果,由于两者都没有历史数据,所以id值较大的服务器2胜出,但是由于没有达到超过半数以上的服务器都同意选举它(这个例子中的半数以上是3),所以服务器1,2还是继续保持查看状态
3,服务器3启动,根据前面的理论分析,服务器3成为服务器1,2,3中的老大,而与上面不同的是,此时有三台服务器(超过半数)选举了它,所以它成为了这次选举的领导者
4,服务器4启动,根据前面的分析,理论上服务器4应该是服务器1,2,3,4中最大的,但是由于前面已经有半数以上的服务器选举了服务器3,所以它只能接收当小弟的命了
5,服务器5启动,同4一样,当小弟
那么,初始化的时候,是按照上述的说明进行选举的,但是当动物园管理员运行了一段时间之后,有机器下降,重新选举时,选举过程就相对复杂了。
需要加入数据version,serverid和逻辑时钟。
version:数据新的版本就大,数据每次更新都会更新版本
server id:就是我们配置的myid中的值,每个机器一个
逻辑时钟:这个值从0开始递增,每次选举对应一个值,也就是说:如果在同一次选举中,那么这个值应该是一致的;逻辑时钟值越大,说明这一次选举领导者的进程更新,也就是每次选举拥有一个zxid,投票结果只取zxid最新的
选举的标准就变成:
1、逻辑时钟小的选举结果被忽略,重新投票
2、统一逻辑时钟后,数据 version 大的胜出
3、数据 version 相同的情况下,server id 大的胜出
根据这个规则选出 leader。
和Paxos的类似,区别如下两点:
raft是基于对多paxos的两个限制形成的:
思考个问题:
为什么需要2N + 1台服务器,发生了宕机,什么情况下会不能使用?
首先只有一个服务器会不稳定,服务器宕机系统就瘫了,2或偶数个的话,脑裂出现,并且分化成的两个集群机器数量均为n,一半选举这个另一半选举那个,此时无法决断,无法进行选举和作出决议,但是如果是奇数个,两个集群机器必然有一多一少,此时以多的为准即可。所以leader选举,要求 可用节点数量 > 总节点数量/2。
2n + 1个台服务器,只要有n + 1个台就可以使用。也就是你说的少于一半集群就无效了