ZooKeeper-9.2 群首选举- 高飞网

9.2 群首选举

2018-06-06 23:14:46.0

    设置群首的目的

    设置群首的目的是为了对客户端所发起的ZooKeeper状态变更请求进行排序,包括create、setData和delete操作。群首将每一个请求转化为一个事务,将这些事务发送给追随者,确保集群按照群首确定的顺序授受并处理这些事务。

   法定数量的解释

    一个服务器必须被仲裁的法定数量的服务器所认可。法定数量必须和集群数量能够交错在一起,以避免脑残问题:即要哪个集合的服务器分别独立运行,形成两个集群。这种情况将导致整个系统状态的不一致性,最终客户端也将其连接的服务器而获得不同的结果。

    何为交错在一起????这里翻译的太烂,就记住法定数量即大于一半的服务器数量就行。

    群首选举过程

    每个服务器启动后进入LOOKING状态,开始选举一个新的群首或查找已经存在的群首,如果群首已经存在,其他服务器就会通知这个新启动的服务器,告知哪个服务器是群首,与此同时,新的服务器与群首建立连接,以确保自己的状态与群首一致。

    如果集群中所有的服务器均处理LOOKING状态,这些服务器之间就会进行通信来选举一个群首,通过信息交换对群首选举达成共识的选择。在本次选举过程中胜出的服务器将进入LEADING状态,而集群中的其他服务器将会进入FOLLOWING状态。

    对于群首选举的消息,称为群首选举通知消息(leader election notifications)。该协议非常简单,当一个服务器进入LOOKING状态,就会向集群中每个服务器服务器发送一个通知消息,该消息中包含该服务器的投票(vote)信息,投票中包含服务器标识符(sid)和最近执行的事务的zxid信息。如(1,5)表示sid=1,zxid=5。

    最终,只有最新的服务器将赢得选举,因为其拥有最近一次的zxid,这样做将简化群首崩溃后重新仲裁的流程,如果多个服务器拥有最新的zxid值,其中sid最大的将赢得选举。

    当一个服务器接收到的仲裁数量的服务器发送的投票都一样时,就表示群首选举成功,如果被选举的群首为某个服务器自己,该服务器将会开始行使群首角色,否则就成为一个追随者并尝试连接被选举的群首服务器。一旦连接成功,追随者和群首之间将会进行状态同步,在同步完成之后,追随者才可以处理新的请求。

    在ZooKeeper中对应的实现选举的Java类为QuorumPeer。其中的run方法实现了服务器的主要工作循环。当进入LOOKING状态,将会执行lookForLeader方法来进行群首的选举,该方法主要执行上面所说的协议,方法返回前,会将服务器状态设置为LEADING状态或FOLLOWING状态,当然还可能为OBSERVING状态。如果服务器成为群首,就会创建一个Leader对象并运行,如果是追随者,就会创建一个Follower对象并运行。

    在现在的实现中,默认的群首选举的实现类为FastLeaderElection。如果想实现自己的群首选举算法,需要实现以下接口:

org.apache.zookeeper.server.quorum.Election

    之所以默认的群首算法称为快速算法,是因为最初的选举算法的实现采用基于拉取式的模型,一个服务器拉取投票值的间隔为1秒,该方法增加了恢复延迟时间,相比现在的实现方式,现在的更加快速地进行群首选举。