zookeeper之工作原理
zookeeper
1.集群角色
zookeeper集群角色分为以下三种:
-
leader:是整个zookeeper集群的核心,负责集群内部各服务器的调度者 ,事物请求的唯一调度和处理者,保证集群事物处理的顺 序性。
-
follower:处理客户端非事物请求、转发事物请求给leader服务器 ,参与Leader选举的投票 ,参与事物请求 Proposal 的投票。
-
observer:Observer 的工作原理与 follower 角色基本一致,而它和 follower 角色唯一的不同 在于 observer 不参与任何形式的投票,只提供非事物请求服务。通常在于不影响集群事物 处理能力的前提下提升集群非事物处理的能力 。
2.zookeeper集群
在zookeeper中,客户端会随机连接到zookeeper集群中 的一个节点,如果是读请求,就直接从当前节点中读取数 据,如果是写请求,那么请求会被转发给leader提交事务, 然后 leader 会广播事务,只要有超过半数节点写入成功, 那么写请求就会被提交(类似2PC事务)
所有事务请求必须由一个全局唯一的服务器来协调处理,这个服务器就是 Leader 服务器,其他的服务器就是follower。leader服务器把客户端的请求转化成一个事务 Proposal(提议),并把这个 Proposal 分发给集群中的所有 Follower 服务器。之后 Leader 服务器需要等待所有Follower服务器的反馈,一旦超过半数的Follower服务器进行了正确的反馈,那么 Leader 就会再次向所有的Follower服务器发送Commit消息,要求各个follower节点对前面的一个Proposal进行提交。
zookeeper工作原理
1.ZAB协议
zookeeper的核心是ZAB协议,ZAB(Zookeeper Atomic Broadcast)协议是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播协议。基于ZAB协议zookeeper来实现分布式数据一致性,保证各个Server之间数据同步。 ZAB协议包含两个模式:崩溃恢复和原子广播。
在zookeeper集群启动阶段或者leader节点出现宕机、网络中断等异常时,ZAB协议就会进入崩溃恢复模式选举出leader服务器。zookeeper选举的核心算法是paxos算法。
2.崩溃恢复模式
ZAB 协议的这个基于原子广播协议的消息广播过程,在正 常情况下是没有任何问题的,但是一旦 Leader 节点崩溃, 或者由于网络问题导致 Leader 服务器失去了过半的Follower节点的联系(leader失去与过半follower节点联 系,可能是leader节点和follower节点之间产生了网络分 区,那么此时的leader不再是合法的leader了),那么就 会进入到崩溃恢复模式。在ZAB协议中,为了保证程序的 正确运行,整个恢复过程结束后需要选举出一个新的 Leader 为了使 leader 挂了后系统能正常工作,需要解决以下两 个问题:
-
已经被处理的消息不能丢失
当 leader 收到合法数量 follower 的 ACKs 后,就向 各个 follower 广播 COMMIT 命令,同时也会在本地 执行 COMMIT 并向连接的客户端返回「成功」。但是如 果在各个 follower 在收到 COMMIT 命令前 leader 就挂了,导致剩下的服务器并没有执行都这条消息。 leader 对事务消息发起 commit 操作,但是该消息在一部分server上执行了,但是一部分server还没有收到 commit, 就已经挂了,而实际上客户端已经收到该事务消息处理成功的回执了。所以在zab协议下需要保证所有机器都要执行这个事务消息。
-
被丢弃的消息不能再次出现
当 leader 接收到消息请求生成 proposal 后就挂了,其他 follower 并没有收到此 proposal,因此经过恢复模式重新选了 leader 后,这条消息是被跳过的。 此时,之前挂了的 leader 重新启动并注册成了 follower,他保留了被跳过消息的 proposal 状态,与整个系统的状态是不一致的,需要将其删除。
如果 leader 选举算法能够保证新选举出来的 Leader 服 务器拥有集群中所有机器最高编号(ZXID最大)的事务 Proposal,那么就可以保证这个新选举出来的Leader一 定具有已经提交的提案。因为所有提案被 COMMIT 之 前必须有超过半数的 follower ACK,即必须有超过半数 节点的服务器的事务日志上有该提案的 proposal,因此,只要有合法数量的节点正常工作,就必然有一个节点保 存了所有被 COMMIT 消息的 proposal 状态。
另外一个,zxid是64位,高32位是epoch编号,每经过 一次 Leader 选举产生一个新的 leader,新的 leader 会将 epoch 号+1,低 32 位是消息计数器,每接收到一条消息 这个值+1,新 leader选举后这个值重置为0.这样设计的好 处在于老的leader挂了以后重启,它不会被选举为leader, 因此此时它的 zxid 肯定小于当前新的 leader。当老的 leader 作为 follower 接入新的 leader 后,新的 leader 会 让它将所有的拥有旧的 epoch 号的未被 COMMIT 的 proposal 清除
3.zxid说明
zxid也就是事务id,为了保证事务的顺序一致性,zookeeper 采用了递增的事 务 id 号(zxid)来标识事务。所有的提议(proposal)都 在被提出的时候加上了 zxid。实现中 zxid 是一个 64 位的 数字,它高32位是epoch(ZAB协议通过epoch编号来 区分 Leader 周期变化的策略)用来标识 leader 关系是否 改变,每次一个 leader 被选出来,它都会有一个新的 epoch=(原来的epoch+1),标识当前属于那个leader的 统治时期。低32位用于递增计数。
4.消息广播模式
消息广播的过程实际上是一个 简化版本的二阶段提交过程 :
-
leader 接收到消息请求后,将消息赋予一个全局唯一的 64位自增id,即为zxid,通过zxid的大小比较既可以实现因果有序这个特征 。
-
leader为每个follower准备了一个FIFO队列(通过TCP 协议来实现,以实现了全局有序这一个特点)将带有zxid的消息作为一个提案(proposal)分发给所有的follower 。
-
当follower接收到proposal,先把proposal写到磁盘, 写入成功以后再向leader回复一个ack。
-
当leader接收到超过半数节点的ACK后,leader就会向这些follower发送commit命令,同时会在本地执行该消息 。
-
当 follower 收到消息的 commit命令以后,会提交该消息 。
整个投票过程observer节点不参与投票,但observer节点需要与leader节点数据保持一直。
5.leader选举
leader选举发生在:zookeeper集群启动时选举和leader服务器异常崩溃时选举。
5.1 zookeeper集群启动时选举
-
每个Server发出一个投票。由于是初始情况,Server1 和 Server2 都会将自己作为 Leader 服务器来进行投 票,每次投票会包含所推举的服务器的myid和ZXID、 epoch,使用(myid, ZXID,epoch)来表示,此时Server1 的投票为(1, 0),Server2的投票为(2, 0),然后各自将 这个投票发给集群中其他机器。
-
接受来自各个服务器的投票。集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票(epoch)、是否来自LOOKING状态的服务器。
-
处理投票。针对每一个投票,服务器都需要将别人的 投票和自己的投票进行比较,比较规则如下
-
优先检查 ZXID。ZXID 比较大的服务器优先作为 Leader
-
如果ZXID相同,那么就比较myid。myid较大的 服务器作为Leader服务器
-
-
统计投票。每次投票后,服务器都会统计投票信息, 判断是否已经有过半机器接受到相同的投票信息,对 于Server1、Server2而言,都统计出集群中已经有两 台机器接受了(2, 0)的投票信息,此时便认为已经选出 了Leader。
-
改变服务器状态。一旦确定了Leader,每个服务器就 会更新自己的状态,如果是Follower,那么就变更为 FOLLOWING,如果是Leader,就变更为LEADING。
5.2 leader服务器异常崩溃时选举
当集群中的 leader 服务器出现宕机或者不可用的情况时, 那么整个集群将无法对外提供服务,而是进入新一轮的 Leader 选举,服务器运行期间的 Leader 选举和启动时期 的Leader选举基本过程是一致的。
-
变更状态。Leader挂后,余下的非Observer服务器 都会将自己的服务器状态变更为 LOOKING,然后开 始进入Leader选举过程。
-
每个Server会发出一个投票。在运行期间,每个服务 器上的ZXID可能不同,此时假定Server1的ZXID为 123,Server3的ZXID为122;在第一轮投票中,Server1 和Server3都会投自己,产生投票(1, 123),(3, 122), 然后各自将投票发送给集群中所有机器。接收来自各 个服务器的投票。与启动时过程相同。
-
处理投票,与启动时过程相同,此时,Server1将会成为Leader。
-
统计投票,与启动时过程相同
-
改变服务器的状态,与启动时过程相同 。