Zookeeper(二):基本原理详解

基本原理

因为只是做下基础知识的讲解,加深对ZK的了解,所以,下面只讲下ZK的两个重要机制

  • 监听机制
  • 选举机制(ZK集群)

一:监听机制

道人画了下简图(MarkDowm画简图,真香!):

创建监听
通知监听对象发生变化
创建监听
通知监听对象发生变化
注册,修改服务
client1
zk_service
client2
service
  • ZooKeeper 提供了分布式数据发布/订阅功能,一个典型的发布/订阅模型系 统定义了一种一对多的订阅关系,能让多个订阅者同时监听某一个主题对象,当 这个主题对象自身状态变化时,会通知所有订阅者,使他们能够做出相应的处理。
  • ZooKeeper 中,引入了 Watcher 机制来实现这种分布式的通知功能。 ZooKeeper 允许客户端向服务端注册一个 Watcher 监听,当服务端的一些事件触 发了这个 Watcher,那么就会向指定客户端发送一个事件通知来实现分布式的通知功能。
  • 触发事件种类很多,如:节点创建,节点删除,节点改变,子节点改变等。

道人概括下,就是客户端在ZK上指定节点创建监听(监听的触发条件可以是节点创建,节点删除,节点改变,子节点改变等),一旦节点发生改变触发监听,ZK会通知客户端。

监听机制的特点

  • 一次性触发
    • 事件发生触发监听,一个watcher event就会被发送到设置监听的客户端, 这种效果是一次 性的,后续再次发生同样的事件,不会再次触发。如果需要再次监听同样的事件,需要再次设置。
  • 事件封装
    • ZooKeeper 使用 WatchedEvent 对象来封装服务端事件并传递。 WatchedEvent 包含了每一个事件的三个基本属性: 通知状态(keeperState),事件类型(EventType)和节点路径(path)
  • event 异步发送
    • watcher 的通知事件从服务端发送到客户端是异步的
  • 先注册再触发
    • Zookeeper 中的 watch 机制,必须客户端先去服务端注册监听,这样事件发 送才会触发监听,通知给客户端。

道人概括下就是:

  • 客户端先注册监听;且监听只会被触发一次(后失效),如果需要再次监听需要再次设置;监听触发后,ZK将通知事件封装异步传递客户端。

监听的命令操作,javaAPI会在道人的后续博客中介绍。

二:选举机制

ZK集群模式下,选取出Leader的方式,最新的算法是FastLeaderElection(默认),判断依据是选票超过半数则选举成功。

涉及概念

  • 服务器ID

    • 比如有三台服务器,zk依次启动时会对服务器进行依次编号分别是 1,2,3。 编号越大在选择算法中的权重越大。(全新集群选举时,哪个ZK服务先启动其sessionID越小。)
  • 选举状态

    • LOOKING,竞选状态。
    • FOLLOWING,随从状态,同步 leader 状态,参与投票。
    • OBSERVING,观察状态, 同步 leader 状态,不参与投票。
    • LEADING,领导者状态。
  • 数据ID

服务器中存放的最新数据 version。
值越大说明数据越新,在选举算法中数据越新权重越大。

  • 逻辑时钟

也叫投票的次数,同一轮投票过程中的逻辑时钟值是相同的。每投完一次票 这个数据就会增加,然后与接收到的其它服务器返回的投票信息中的数值相比, 根据不同的值做出不同的判断。

选举机制大致流程图

ZK选举流程图

举个栗子

在这里插入图片描述

首先道人介绍下选举时几个原则,帮助各位道友理解。

  • 每当一个ZK节点加入集群中,获取当前节点的Zxid(也是递增),并使逻辑时钟的值+1,新的ZK节点向其他节点广播的逻辑时钟值大于其保存的逻辑时钟值,表明有新的节点加入集群,便从新开始一次选举。
  • 每个新加入节点,会将选票投给自己,同时通知其他节点从新投票,投票原则是,将票投给Zxid最大的节点(也可理解新加入节点)。
  • 判断规则为节点选票大于半数,则选择的节点选举为leader,而一旦选举为leader,,自身状态会变为leading,其之前节点状态会有Looking变为Following则后续加入节点,不可能成为leader,只能作为Follower。

再简化说下原则:

  • 原则一:选票投最大Zxid节点,**超过半数则选举出Leader。**直到选举出Leader,集群才能正常工作。
  • 原则二:节点加入(Looking状态),则开启新一轮选举,其他节点更改选票,根据原则一,判断是否选举出Leader。
  • 原则三:Leader选举出来后,选举为Leader的节点状态修改为Leading,其他节点从Looking修改为Following,后续节点均为Follower

以五个节点的ZK服务集群为例(这里的服务器后1,2,3,4,5;可以理解为zk服务的Zxid)

(1)服务器1启动,发起一次选举。

服务器1投票给自己,发现选票小于半数,无法完成选举。
服务器1状态保持为LOOKING;

(2)服务器2启动,再发起一次选举。

服务器1和2分别投自己一票,此时服务器1发现服务器2的Zxid比自己大,更改选票投给服务器2;

发现选票小于半数,无法完成选举。

服务器1,2状态保持为LOOKING;

(3)服务器3启动,发起一次选举。

服务器1,2,3分别投自己一票,服务器1和服务器2更改选票投给Zxid更大的服务器3;

此次投票结果:服务器1为0票,服务器2为0票,服务器3为3票。此时服务器3的票数已经超过半数(3票),服务器3当选Leader。

服务器1,2更改状态为FOLLOWING,服务器3更改状态为LEADING;

(4)服务器4启动,发起一次选举。

此时服务器1,2,3已经不是LOOKING状态,不会更改选票信息。交换选票信息结果:服务器3为3票,服务器4为1票。

此时服务器4服从多数,更改选票信息为服务器3;

服务器4并更改状态为FOLLOWING;

(5)服务器5启动(情况与服务器5相同);

服务器5并更改状态为FOLLOWING;

上述过程的选举流程图如下:

在这里插入图片描述


上述讲解的是全新集群选举(即集群启动时选举的机制),下面介绍下非全新集群选举(集群启动后有节点宕机的情况)。

非全新集群选举

对于运行正常的 zookeeper 集群,中途有节点宕机,需要重新选举时, 选举过程就需要加入数据 ID、服务器 ID 和逻辑时钟。

概念:

  • 数据 ID:数据新的 version 就大,数据每次更新都会更新 version。
  • 服务器 ID:就是我们配置的 myid 中的值,每个机器一个。
  • 逻辑时钟:这个值从 0 开始递增,每次选举对应一个值。 如果在同一次选举 中,这个值是一致的。

选举原则:

  • 逻辑时钟小的选举结果被忽略,重新投票;
  • 统一逻辑时钟后,数据 id 大的胜出;
  • 数据 id 相同的情况下,服务器 id 大的胜出;

其余选举过程等同于全新集群选举。

道友们都看到这了,有收获的话,点个赞再走呗!道人在此谢过了!
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章