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 同步)