Zookeeper集群角色, 部署个数, leader选举

转自: https://www.jianshu.com/p/17a2badf669e

上面是zookeeper集群的工作模式, 下面来介绍一下集群中的几个角色:

一. Leader角色

Leader 服务器是整个 zookeeper 集群的核心,主要的工作任务有两项

1.事务请求的唯一调度和处理者,保证集群事务处理的顺序性。
2.集群内各个服务的调度者。

在zookeeper中,客户端会随机连接到zookeeper集群中的一个节点,如果是读请求,就会直接从当前节点读取数据,如果是写请求(这里应该说是事务请求,也就是涉及事务操作的增删改),如果该节点不是leader角色,就会转发给leader角色,由leader角色负责处理事务,然后leader就会广播事务,只有超过半数的节点写入数据成功,那么写请求才会被提交。

leader角色在整个集群中是唯一的,这里zookeeper设计会考虑到单点故障问题,如果leader宕机了,那么就会通过选举算法进行选举出新的leader出来,然后这个节点会进行重启。那么如何保证数据的一致性我们后面再来说。当leader宕机会由Observer通过心跳检测到,一般设置为两秒。这时候就会通过zab协议进行选举新的leader出来,然后进行崩溃恢复。

二. Follow角色

follow角色的主要指责就是如下:

1.处理客户端非事务请求、转发事务请求给leader服务器。
2.参与事务的Proposal投票(需要半数以上服务器通过才能通知leader commit数据)。
3.参与leader选举的投票。

三. Observer 角色

Observer 是 zookeeper3.3 开始引入的一个全新的服务器角色,从字面来理解,该角色充当了观察者的角色。 观察 zookeeper 集群中的最新状态变化并将这些状态变化同步到 observer 服务器上。Observer 的工作原理与follower 角色基本一致,而它和 follower 角色唯一的不同在于 observer 不参与任何形式的投票,包括事物请求Proposal 的投票和 leader 选举的投票。

简单来说,observer服务器只提供非事物请求服务,通常在于不影响集群事物处理能力的前提下提升集群非事物处理的能力。

每个节点的状态跟节点的角色类似,主要包含LOOKING,LEADING, FOLLOWING和OBSERVING四种。
1. LOOKING:不确定leader节点的状态,此时该节点会认为当前集群不存在leader节点,故会主动发起一次leader选举,广播选举包,即投给自己,给其他节点。此时leader节点收到后会将自己的LEADING状态告诉该节点并投票给leader自身,其他follower节点收到后,则是将自己的FOLLOWING状态告诉该节点并投票给leader节点,该节点收到leader和其他follower的状态和投票后,知道当前leader节点的信息,并通过其他follower的投票确认该leader节点确实是leader节点,则设置自身状态为FOLLOWING,成为当前leader的follower节点。
2. FOLLOWING:跟随者状态,即自身角色是follower。
3. LEADING:领导状态,自身角色为leader,并且维持着与follower和observer的心跳。
4. OBSERVING:观察者状态,即自身角色是observer。

关于Leader选举

当ZooKeeper集群中的一台服务器出现以下两种情况之一时,就会开始进入Leader选举

  • 服务器初始化启动
  • 服务器运行期间无法和Leader保持连接
leader选举时,每个follower节点的投票包的相关核心数据如下:
1. logicalClock:该节点发起的第几轮投票,每选举一次加1;
2. self_id:当前节点自身的myid;
3. self_zxid:当前节点自身所保存的数据的最大zxid,越大说明处理了越多数据写请求;
4. vote_id:当前节点投票给的节点的myid;
5. vote_zxid:当前节点投票给的节点的数据的最大zxid。
选举的过程:
  1. leader选举开始时,每个follower节点首先清空自己的投票箱,然后投票给自己,并通过广播的方式通知所有其他节点给自己投票;
  2. 每个follower节点接收到其他follower节点的选票,将该外部选票与自己的选票进行对比,对比主要是基于5个核心数据项来展开:
    1. 选举轮次:比较logicalClock,如果外部选票的logicalClock大于自己的,则说明自己的选举轮次落后于该外部节点了,则清空自己的投票箱,并将自己的投票更新为当前轮次后重新广播投票出去;小于则忽略该外部选票;等于则进入下面步骤继续比较其他数据;
    2. vote_zxid大小比较:将外部选票的vote_zxid与自己的投票的vote_zxid进行对比,如果外部的大,则将自己的(vote_id,vote_zxid)更新为该外部选票的vote_id和vote_zxid并广播出去,即投给这个vote_zxid更大的vote_id;并更新自身的投票箱,即添加或者更新该外部投票对应的vote_id的选票情况。还有一点: 在每个节点自己的投票箱中,每个参与投票的follower节点只能存在一张投票,也就是说, 如果当前节点收到某个节点的多次投票时,则需要进行覆盖. 比如: 节点A刚开始收到节点B投给B自己的投票,A放入投票箱为(B,B),后来A又收到B投给C的通知,则更新为(B,C),此时A的投票箱不再存在(B,B)的这种选票了,而是更新为了(B,C);
    3. vote_id大小比较:如果vote_zxid相同,则投票给vote_id更大的节点;
    4. 重复以上过程,当某个节点发现过半数的follower节点都投给了自己,则更新自己的状态为LEADING,其他节点则更新自己的状态为FOLLOWING,投票结束。接下来进入数据同步阶段。
    5. 数据同步阶段:主要是新的leader节点将自己commit的数据同步给其他follower节点。

关于集群部署的个数原理

通常 zookeeper 是由 2n+1 台 server 组成,每个 server 都知道彼此的存在。对于 2n+1 台 server,只要有 n+1 台(超过半数)server 可用,整个系统保持可用。

我们已经了解到,一个 zookeeper 集群如果要对外提供可用的服务,那么集群中必须要有过半的机器正常工作并且彼此之间能够正常通信,基于这个特性,如果向搭建一个能够允许 N 台机器down 掉的集群,那么就要部署 2*N+1(奇数) 台服务器构成的zookeeper 集群。

因此, 3 台机器构成的 zookeeper 集群,能够在挂掉一台机器后依然正常工作。5 台机器集群的服务,能够对 2 台机器怪调的情况下进行容灾。如果一台由 6 台服务构成的集群,同样只能挂掉 2 台机器。因此, 5 台和 6 台在容灾能力上并没有明显优势,反而增加了网络通信负担。

总之,之所以要满足这样一个等式,是因为一个节点要成为集群中的 leader,需要有超过及群众过半数的节点支持,这个涉及到 leader 选举算法。同时也涉及到事务请求的提交投票。

发表评论

电子邮件地址不会被公开。 必填项已用*标注