zookeeper原理-leader选举及请求处理

一. 引言:

   ZooKeeper 作为分布式协调服务,其核心能力依赖于强一致性的数据同步和高可用的集群架构,而这一切的基础是 Leader 选举机制和基于 Zab 协议的请求处理流程。本文将深入解析这两大核心原理。

二. 关于leader选举:

 一个zk集群,通常包含三个角色,分别为:领事( leader),追随者(follower),观察者(observer):

 1.   leader: 作为中心处理所有对zk系统变更对请求,类似一个定序器,建立了所有对zk状态对更新的顺序。
 2.  follower:接受leader锁发出的更新操作请求,进行相关处理,以此来保障状态更新操作不会发送碰撞。
 3.  observer:不会参与决策哪些请求可被接受的过程,只是观察决策的结果,观察者的设计只是为了系统的可扩展性。

leader需要得到法定节点数一直认可后才会进行leader选举,法定节点数为> 集群总节点数/2 。否则,点那个节点异常时,容易出现“脑裂”情况。因此集群节点当尽可能的选择为>=3的奇数。

leader选举:

  leader为集群中服务器选择出来的一个服务节点,并会一直被集群所认可。设置leader的目的是为了对客户端所发起对zk状态变更请求(create,delete,setData)进行排序。leader将每个请求转化为一个事务,将这些事务发送给follower,确保集群按照leader确定对顺序处理相关事务。

通常情况下,leader分为两种情况,分别为新建集群和运行中的选举。

a) . 新建集群:

Server1   myid:1 zxid:0
Server2   myid:2 zxid:0
Server3   myid:3 zxid:0

    每个服务器启动后进入LOOKING状态,相互之间会通过信息交换(比较myid/sid,zxid )对leader选举达成共识。胜出的节点进入leading状态,其他节点进入following状态。对于leader的选择协议很简单: 当服务节点进入LOOKING状态,就会向集群中所有节点发起一个通知,内容包括:投票(vote)信息,服务节点标识符(myid/SID)和最近执行事务的zxid信息。投票流程如下:

 1.  每个服务节点都会发起投票请求,投票(vote)信息,服务节点标识符(myid/SID)和最近执行事务的zxid信息。
 2.  每个服务器收到其他服务器的投票,先会检查有效性包括检查是否是本轮投票以及是否来自LOOKING状态的服务器发出的。
 3.  处理投票: 首先比较ZXID,值最大的为Leader,如果值一样那么就比较myid,myid最大的为Leader,Server1会收到(1,0)(2,0)(3,0)经过比较自己的myid不是最大的,它会重新投票新的投票(3,0)并从新发到集群中去,对于Server2也一样,对于Server3来说它不用更新投票信息它比较后自己就是最大的所有再次发出投自己的票就可以。这样每个机器又会收到2个投票信息,Server1会收到Server2、3发来的(3,0)。
 4.  每次投票服务器都会进行投票统计,判断是否有超过半数机器相同的投票信息,对于这三台服务器来说最终投票结果是(3,0),那么除了Server3之外其他都会收到2张(3,0)的投票,这样在一个3台集群中超过半数投票是投给一个机器的,那么这个机器就是集群的Leader。
 5.  一旦确定了Leader那么就需要设置自己的角色以及改变自己的状态Leader变成LEADING,而Follower就变成FOLLOWING。

b).  运行中的选举:

    当集群中的服务器数量发生变化时才会进行重新选举, 如:leader故障,或者新增服务节点。

Server1   myid:1 zxid:123
Server2   myid:2 zxid:122
Server3   myid:3 zxid:(宕机)

选举流程如下:

  1.  当集群服务节点感知到Leader挂了,那么所有Follower角色的服务器就转变状态从FOLLOWING变成LOOKING
  2.  每个服务器发出投票Server1会发出(1,123)到集群中,Server2会发出(2,122)到集群中。
  3.  各节点收到其他人的投票信息。与启动时的原则一样, Server1因为它的ZXID比Server2的大,所以它会发一个投自己的票,Server2发现自己的ZXID小所以更新投票信息(1,123)再次发出去。
  4.  统计投票信息,最终Server1胜出成为Leader。
  5.  改变节点状态。

三. 请求处理,事务,标识符:

    zk服务会在本地处理制度请求(exists, getdata和getChildren) ,zk在处理以“只读”为主要负载时,性能会很高,可以通过增加服务节点到集群中,从而提高整体处理能力。

   当遇到“会改变zk状态”的客户端请求(create,delete,setData)时,将会被转发给leader,leader执行相应请求,并形成状态的更新,称之为:事务。

   一个事务为一个单位,也就是说所有的变更处理需要以原子方式执行。以setData为例,变更节点的数据信息,但并不改变版本号,将会导致错误但发送,无法进行变更。因此,zk集群以事务方式运行,并确保所有的变更操作以原子方式被执行,同时不会被其他事务所干扰(最开始,zk以在每个服务器中启动一个单独的线程处理事务,保障事务之间的顺序不被干扰,目前增加了多线程的支持,以便提高处理速度)。事务具有幂等性(重复操作结果一样)。

   当leader产生了一个事务,就会 为该事务分配一个标识符,称之为“会话ID(zxid)”, 通过zxid对事务进行标示,就可以按照leader所制定的顺序在各服务节点中按顺序执行。服务节点之间在进行新的leader选举时也会交换zxid信息,从而知道哪个无故障节点接受了更多的事务,进行同步。 

请求流程:

  当接受到一个写请求时,follower会将请求转发给leader,leader将探索性执行该请求,并将执行结果以事务方式对状态更新进行广播。当事务提交时,server会将相关变更反馈到数据树(zk用于保存状态信息到数据结构) 。通过zab(zookeeper原子广播协议)确认一个事务是否提交。提交流程大致如下:

   1. leader向所有follower发送一个proposal消息p。
   2. 当一个follower接受到消息p后,会响应leader一个ack消息,通知leader已接受该提案。
   3. 当leader接受到仲裁数量的follower发送的确认消息后(仲裁数量包括leader自己),leader就会发送消息通知follower进行提交操作。

在应答提案之前,follower还会检查所发送的提案消息是否属于所追随的leader,并确认leader所广播的提案信息和提交事务消失的顺序正确。

zk通过时间戳的方式记录管理权随时间的变化情况,一个时间戳表示某个server行使管理权的这段时间,在一个时间戳内,leader会广播提案消息,并根据计数器识别每一个消息。zxid的第一个元素为时间戳信息,因此每个zxid可以很容易与事务被创建的时间戳相关联。时间戳的值在每次新leader选举发生的时候都会增加。

zab协议提供了以下保障:

   1. 一个被选举的leader确保在提交完所有之前的时间戳内需要提交的事务,之后才开始广播新的事务。
   2. 在任何时间点,都不会出现两个被仲裁支持的leader

因为写请求的处理机制(需要等到仲裁数量的follower确认信息)。在大集群(集群越大,节点越多,仲裁节点数越多,写吞吐量越低,效率越低)中,为了提高写操作效率,zk提供了一个"观察者(observer)" 的角色,功能和follower一样,只是不参与投票仲裁,提高读效率。

 - --------------------------------------------------------------------------------------------------------------------------

                         深耕运维行业多年,擅长运维体系建设,方案落地。欢迎交流!

                                                     “V-x”: ywjw996

                                                     《 运维经纬 》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值