ZooKeeper ZAB原子广播协议

 

在zookeeper中,主要依赖ZAB( ZooKeeper Atomic Broadcast , ZooKeeper 原子广播协议)协议来实现分布式数据一致性,基于该协议,zookeeper实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。

 

在zookeeper的集群中,采用一个单一的主进程来接收并处理客户端的事务请求,采用ZAB协议将服务器数据的状态变更以事务Proposal的形式广播到所有的副本进程上去。Zab协议包含两种模式,分别是崩溃恢复和消息广播。

 

数据一致性的保证(zab原子广播协议):

CAP分为,一致性(C),可用性(A),和分区容错性(P)。根据CAP原理,3者只能同时保证两个,作为一个分布式系统,分区容错是必须要考虑的一个关键点,如果如果丧失分区容错也就意味着放弃了扩展性。因为分布式系统中,网络故障经常出现,一旦出现这种问题将会导致整个系统的不可用,这是绝不容忍了,所以大多数框架都只是在CA上做权衡。

因为zookeeper是分布式协调服务器,他的职责就是保证数据在管辖范围内完成服务器之间的同步,所以在C和A上zookeeper选择了C强一致性,所以在可能会导致某些时候我们访问的时候无效需要我们重复访问。不扯这么多了下面来一步步分析一下zookeeper是如何来做到的吧:

 

Zookeeper是一个高性能高可用的一致性框架,提到高性能,最常见也是最有效就是通过集群部署突破单机的瓶颈,来提高性能。传统的集群架构是master/slave模式,而在zookeeper中做了改进,有了新的变化,有了下面几个新的角色:

 

扫描二维码关注公众号,回复: 12391069 查看本文章

 

Leader:zk中的老大,再整个集群中只有一个,可以对外提供读写服务,但是在zk集群中,所有的写请求都集中在这个leader节点中

Follower:提供读服务器,转发写请求给leader,并且当leader挂掉之后,follow节点会参与选举,选择一个leader对外提供服务

Observer:follow和observe节点都可以对外提供服务,唯一区别是Observer机器不参与leader选举过程,也不参与操作“过半写成功”策略,他的作用是在不影响写性能的情况下提升集群的读性能

 

消息广播:

zk事务提交的过程其实类似2pc提交但是移除了中断逻辑,所有的事务请求必须由一个全局唯一的服务器来协调处理,这样的服务器被称为leader服务器,其余的就是follower服务器。Leader服务器负责将一个客户端事务请求转化成一个事务Proposal(提议),并将该Proposal分发给集群所有的Follower服务器。之后Leader服务器需要等待所有的Follower服务器的反馈,一旦超过半数的Follower服务器进行了正确的返回后,那么Leader将会再次向所有的follower服务器发送Commit消息,将前一个proposal进行提交。

 

1:Leader收到包装写请求,生成唯一且自增的事务ID(也就是zxid),发起协议广播给所有的follow,因为协议要保证严格的因果关系,所以每一个事务proposal都是按照zxid的顺序进行排序和处理。

2:Follow收到Proposal提议之后,首先会将事务日志写到本地磁盘上去,成功写入到本地磁盘上去之后,返回给leader一个ACK。

3:当leader服务器接收到了过半数follow的Ack响应后,就会广播一个commit消息给所有的follow服务器通知他们进行事务提交,同时leader服务器自身也会完成事务提交。

 

需要提一句的是,zookeeper对于数据一致性的要求是:

1:顺序一致性:严格按照事务发起的顺序执行写操作

2:原子性:所有的事务请求结果在集群中的所有节点上的应用情况是一致的

3:单一视图:客户端访问任何节点看到的都数据模型都是一致的

4:可靠性:一旦一个事务提交了,那个该事务一定会保留下

5:实时性:保证在极小的一段时间客户端最终可以从服务器读取到最新的数据状态

 

 

(留个疑问,zk只能有一个leader节点,如果发生单节点故障怎么办,那么它的leader选举应该是非常高效,后面咱们再慢慢看)

 

崩溃恢复

上面提到了,在zk集群中,所有的写请求都集中在一个leader节点上,当整个服务框架在启动过程中,或者是当leader服务器出现网络中断、崩溃退出与重启等异常状况时:

因为ZAB协议需要确保那些已经在leader服务器上提交的事务最终被所有的服务器都提交,并且丢弃只在leader服务器上提出的事务。

(假设一个事务在leader服务器上被提交了,并且已经得到过半follower服务器ack反应,但是在它将commit消息发送给所有follower机器之前,就是还有一些follower服务器没有接收到commit消息,leader服务器挂了,zab协议需要保证所有的fellower服务器都能够接受proposal,)

 

选举步骤如下:

1:follower节点先投票自己,然后将自己的选票广播给剩余follower节点

2:follower节点收到其他的选票,然后和自己的选票进行比较

3:如果自己的选票不是最优选票,那么变更自己的选票,投最优选票节点

4:统计自己收到的选票,如果某个节点获得了过半的投票,确定该节点为新的leader节点。

5:确认leader节点后,每个节点变更角色,投票结束。

 

定义的投票结构为:[投票节点ID,被投票节点ID,被投票节点最大事务ID]
(这里的票数统计为什么要选择最大的事务ID呢?其实因为我们的proposal是顺序且自增形式进行提交的,我手上的票数大,肯定就说明我们的最新)

 

数据同步:

当完成leader选举之后,正式开始工作之前(既接收客户端的请求),leader服务器首先会确认事务日志中的所有proposal是否已经被集群中的过半机器提交,这个过程就是ZAB协议的数据同步过程。

所有正常运行的服务器,要么成为leader,要么成为follower冰河leader保持同步,leader的职责就是确保所有的follow服务器能够接受到每一条已提交事务proposal到内存数据库中,具体过程如下:

 

1:Leader为每一台follower服务器准备一个队列,查看没有同步的事务

2:Leader那些提交以proposal消息发送给follower,并且紧跟着一条commit消息,标识该事物已经被提交

3:Follower服务器将所有未同步的事务proposal都从leader服务器上同步过来并成功应用到本地数据库中后,leader服务器就会将该follower服务器加入到真正可用的follower列表中

 

参考书籍:《从PAXOS到ZOOKEEPER分布式一致性原理与实践》

猜你喜欢

转载自blog.csdn.net/qq_25448409/article/details/84859278