Zookeeper(6)进阶

152 阅读7分钟

1.Zookeeper是什么

文件系统:zookeeper的文件系统通过znode节点构成,每个znode节点,既可以表示路径,也可以包含数据,为了保持zookeeper的高效性,zookeeper的节点不能够太大,每个节点存放的数据上限为1M

通知机制:在不同的节点注册watcher,当节点发生改变时,会通知客户端节点状态的改变

2.Zookeeper节点的四种类型

(1)PERSISTENT-持久节点:除非手动删除,否则节点一直存在于 Zookeeper 上

(2)EPHEMERAL-临时节点:临时节点的生命周期与客户端会话绑定,一旦客户端会话失效(客户端与zookeeper 连接断开不一定会话失效),那么这个客户端创建的所有临时节点都会被移除。

(3)PERSISTENT_SEQUENTIAL-持久顺序节点:基本特性同持久节点,只是增加了顺序属性,节点名后边会追加一个由父节点维护的自增整型数字。

(4)EPHEMERAL_SEQUENTIAL-临时顺序节点:基本特性同临时节点,只是增加了顺序属性,节点名后边会追加一个由父节点维护的自增整型数字。

3.Zookeeper的watcher机制

(一)watcher机制的过程

Zookeeper 允许客户端向服务端的某个 Znode 注册一个 Watcher 监听,当服务端的一些指定事件触发了这个 Watcher,服务端会向指定客户端发送一个事件通知来实现分布式的通知功能,然后客户端根据 Watcher 通知状态和事件类型做出业务上的改变。

(二)watcher机制的特性

「一次性:」 一个Watch事件是一个一次性的触发器。一次性触发,客户端只会收到一次这样的信息。

「异步的:」 Zookeeper服务器发送watcher的通知事件到客户端是异步的,不能期望能够监控到节点每次的变化,Zookeeper只能保证最终的一致性,而无法保证强一致性。

「轻量级:」 Watcher 通知非常简单,它只是通知发生了事件,而不会传递事件对象内容。

「客户端串行:」 执行客户端 Watcher 回调的过程是一个串行同步的过程

(4)watcher的注册:在new Zookeeper的时候,可以给会话注册监听器, 也可以在调用getData、exists、getChildren时给节点注册监听器

(5)watcher的触发:create、delete、setData的时候

4.Zookeeper集群服务器的角色

(1)Leader

事物请求的唯一调度者和处理者,保证处理事物的有序性

负责发起集群内部的投票,更新系统状态

(2)Follower

处理客户端的非事物请求,转发事物请求给Leader服务器

参与事务请求的提交的投票

参与Leader选举的投票

(3)Observer

在不影响集群事务处理能力的基础上提升集群的非事务处理能力

处理客户端的非事务请求,转发事务请求给 Leader 服务器

不参与任何形式的投票

5.Zookeeper下的服务器状态

服务器具有四种状态,分别是 LOOKING、FOLLOWING、LEADING、OBSERVING。

(1)LOOKING:寻 找 Leader 状态。当服务器处于该状态时,它会认为当前集群中没有 Leader,因此需要进入 Leader 选举状态。

(2)FOLLOWING:跟随者状态。表明当前服务器角色是 Follower。

(3)LEADING:领导者状态。表明当前服务器角色是 Leader。

(4)OBSERVING:观察者状态。表明当前服务器角色是 Observer。

6.Zookeeper的zab协议

zookeeper通过zab协议保证事务执行的一致性,通过类似两段提交协议的方式解决数据的一致性

zab协议的处理过程:

(1)leader接收到一个写请求

(2)leader会生成一个性的事务并为这个事务生成一个唯一的事务ZXID

(3)leader将这个事务提议发送给所有的fellower节点

(4)follower节点将收到的事务请求加入到历史队列(history queue)中,并发送ack给leader

(5)当leader收到大多数follower(半数以上节点)的ack消息,leader会发送commit请求

(6)当follower收到commit请求时,从历史队列中将事务请求commit

7.zookeeper的集群配置

在配置文件中申明其他的zookeeper服务器即可

8.Zookeeper服务器的leader选举过程

(一)服务器启动时的leader选举

当集群启动时,只有一台服务器server1时,无法进行leader的选举,当第二台服务器server2启动时,两台机器可以通信,每台机器试图找到leader,于是进入到选举的过程,选举过程如下:

(1)每个server发出一个投票。由于是初始情况,server1和server2都会将自己作为leader服务器来进行投票,每次投票会包含所推举的服务器的myid和zxid,使用(myid, zxid)来表示,myid为节点编号,zxid为事物编号。此时server1的投票为(1, 0),server2的投票为(2, 0),然后各自将这个投票发给集群中其他机器。

(2)集群中的每台服务器接收来自集群中各个服务器的投票。

(3)处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行pk,pk规则如下:

优先检查zxid。zxid比较大的服务器优先作为leader。如果zxid相同,那么就比较myid。myid较大的服务器作为leader服务器。 对于Server1而言,它的投票是(1, 0),接收Server2的投票为(2, 0),首先会比较两者的zxid,均为0,再比较myid,此时server2的myid最大,于是更新自己的投票为(2, 0),然后重新投票,对于server2而言,其无须更新自己的投票,只是再次向集群中所有机器发出上一次投票信息即可。

(4)统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息。

对于server1、server2而言,都统计出集群中已经有两台机器接受了(2, 0)的投票信息,此时便认为已经选出了leader

(5)改变服务器状态。一旦确定了leader,每个服务器就会更新自己的状态,如果是follower,那么就变更为following,如果是leader,就变更为leading

(二)服务器运行时的leader选举

假设正在运行的有server1、server2、server3三台服务器,当前leader是server2,若某一时刻leader挂了,此时便开始Leader选举。选举过程如下:

(1) 变更状态。leader挂后,余下的服务器都会将自己的服务器状态变更为looking,然后开始进入leader选举过程。

(2) 每个server会发出一个投票。在运行期间,每个服务器上的zxid可能不同,此时假定server1的zxid为122,server3的zxid为122,在第一轮投票中,server1和server3都会投自己,产生投票(1, 122),(3, 122),然后各自将投票发送给集群中所有机器。

(3)接收来自各个服务器的投票。与启动时过程相同

(4)处理投票。与启动时过程相同,此时,server3将会成为leader。

(5)统计投票。与启动时过程相同。

(6)改变服务器的状态。与启动时过程相同。

9.数据的同步

(一)数据同步的类型

(1)直接差异化同步(DIFF 同步)

(2)先回滚再差异化同步(TRUNC+DIFF 同步)

(3)仅回滚同步(TRUNC 同步)

(4)全量同步(SNAP 同步)

(二)同步操作

整个集群完成 Leader 选举之后,Learner(Follower 和 Observer 的统称)回向Leader 服务器进行注册。当 Learner 服务器想 Leader 服务器完成注册后,进入数据同步环节。

事务标志:

peerLastZxid: 从服务器注册时发送的 ACKEPOCH 消息中提取 lastZxid(该Learner 服务器最后处理的 ZXID)

minCommittedLog: Leader 服务器 Proposal 缓存队列 committedLog 中最小 ZXID

maxCommittedLog:Leader 服务器 Proposal 缓存队列 committedLog 中最大 ZXID

(一)全量同步,peerLastZxid 小于 minCommittedLog

peerLastZxid 小于 minCommittedLog

Leader 服务器上没有 Proposal 缓存队列且 peerLastZxid 不等于 lastProcessZxid

(二)直接差异化同步,peerLastZxid 介于 minCommittedLog 和 maxCommittedLog之间

peerLastZxid 介于 minCommittedLog 和 maxCommittedLog之间先回滚再差异化同步(TRUNC+DIFF 同步)

(三)回滚,peerLastZxid 大于 maxCommittedLog

当新的 Leader 服务器发现某个 Learner 服务器包含了一条自己没有的事务记录,那么就需要让该 Learner 服务器进行事务回滚–回滚到 Leader服务器上存在的,同时也是最接近于 peerLastZxid 的 ZXID仅回滚同步(TRUNC 同步)