浅谈分布式协调服务之Zookeeper

1. Zookeeper是什么?
Zookeeper是一个开源的分布式协调服务。有雅虎创建,是Google chubby的开源实现。Zookeeper的设计目标是将那些复杂容易出错的分布式一致性服务给封装起来,构成一个高效可靠的原语集,并且提供一系列简单的接口给用户使用。
2. 分布式协调服务是什么?
看名应该猜想到的是一个起到协调作用的分布式服务。那么现实生活中什么时候需要协调呢?我们应该都清楚的是比如:A和B同学为了某一样东西发生争执的时候,这个时候需要有个好人在他们中间进行合理的调解。那么术语中是怎么描述的呢?分布式协调服务是用来解决分布式环境中多个进程之间的同步控制,让他们有序的去访问某种临界资源,防止造成“脏数据”的后果。
3. 背景
一个节点有多个集群时,如下图:问题的抛出


案例可以看出,分布式出现了很多难题的原因都是缺少了一个协调机制造成。在分布式协调上做得比较好的有Google chubby和Apache zookeeper。
Zookeeper基于Google chubby的思想开发。当时在雅虎公司内部存在很多系统都依赖于一个系统来进行分布式协调,但是Google chubby不开源,所以就自主研发了zookeeper并捐献给Apache。
引入zookeeper后的问题的解决;如下图:


4. Zookeeper的数据模型(Znode)
Zookeeper的数据模型与标准的文件系统非常的相似;如下图:


Znode特性:1、同级节点唯一性;2、临时节点和持久化节点;3、有序节点;4、临时节点不能存在子节点。
Znode属性:


5. Zookeeper的ZAB协议
首先了解为什么需要ZAB协议?由于在zookeeper集群中是属于中心化的集群,那么如果leader挂了怎么办?如何保证leader和follower数据的一致性问题?
为了解决上述问题,zookeeper专门设计了支持崩溃恢复的原子广播协议,即ZAB协议。
ZAB协议介绍:
ZAB协议包含两种基本模式:1、崩溃恢复;2、原子广播。
整个集群在启动时,或者当leader网络出现中断、崩溃时,ZAB协议就会进入恢复模式并选举产生新的leader,当 leader 服务器选举出来后,并且集群中有过 半的机器和该 leader 节点完成数据同步后(同步指的是数 据同步,用来保证集群中过半的机器能够和 leader 服务器 的数据状态保持一致),ZAB 协议就会退出恢复模式。 当集群中已经有过半的 Follower 节点完成了和 Leader 状 态同步以后,那么整个集群就进入了消息广播模式。这个 时候,在 Leader 节点正常工作时,启动一台新的服务器加 入到集群,那这个服务器会直接进入数据恢复模式,与leader节点进行数据同步。同步完成后即可正常对外提供非事务请求的处理。
a 什么是原子广播?
原子广播类似于2PC,是一个简化版本的二阶段提交过程。
原子广播实现原理:
在集群中,由于zookeeper是中心化集群(与redis不同)。那么对于一些事务性请求都会被转发至leader机器处理,follower只能处理一些非事务性请求。
1) leader接收到事务性请求后,将消息赋予一个全局唯一的64位ID,即zxid;通过zxid即可实现因果有序的特征;
2) leader为每一个follower都准备了一个FIFO队列(由TCP实现),这样实现了全局有序的特征;经过FIFO队列将每个消息作为一个提案分发给每一个follower;
3) 当follower接收到提案后,先把提案写入磁盘,并且写入成功后向leader返回一个ack;
4) 当leader收到合法数量(超过半数节点)的ack后,leader就会向follower发送commit命令,同时本地执行commit;
5) 当follower接收到commit后,执行本地commit;


b 什么是崩溃恢复(节点数据恢复)?
崩溃恢复是在leader节点网络中断失去过半follower的通讯时,需要进行重新选举leader和数据同步。在整个恢复过程后必须要选出新的leader,并且要保证新的的leader在就leader恢复后,新leader不会被动摇。
那么在此过程中就涉及了2个问题
1) 已经提交过的数据不能被丢失
我们将leader的生命周期看成非常的脆弱。假设在上图中,接收到过半的ack后开始发送commit命令时,半途中leader挂了,那么可能会存在follower1接收到commit命令,而follower2没有接收到commit命令,那么在zab协议下需要保证这个事务请求在整个集群中是不能丢失的。


2) 没有提交过的数据不能再次出现(旧leader恢复)
假设在leader接收到提案后,leader节点挂了,那么此时会进入恢复模式,等到选出了新的leader后,此时就leader恢复,这个时候由于就leader中有存在于其他节点中不一致的数据,那么它再次发起提案后,此时其他的follower应该是要过滤掉此提案,并且需要删除此数据。
ZAB协议需要满足上述两点,就需要设计出一个leader选举的算法,能够确保已经被提案且部分节点有提交过的数据不能丢失、同时丢弃已经被跳跃过的提案。
针对这个要求:如果新leader在集群中zxid是最大的,那么就能保证新leader的所具有的数据是最全面的。因为被commit之前,必须是过半的ack返回后才有commit命令,说明这个提案在原leader中是需要执行的。另一个是在前述中有提到zxid,比较zxid大小,它是一个64位的全局唯一ID,其中高32位是epoch编号,低32位是事务编号。epoch可以理解为朝代,当leader重新选取时会+1,并存在currentEpoch文件中;事务编号就是在每次进行事务请求是都会在原来基础上+1;如果重新选举leader了就重新开始计算。有了这个机制后当旧的leader重新恢复后,将它本地待提案的消息重新发送给其他follower时,其他follower的zxid都是比它大,所以可以直接过滤。
关于 ZXID
zxid,也就是事务 id, 为了保证事务的顺序一致性,zookeeper 采用了递增的事 务 id 号(zxid)来标识事务。所有的提议(proposal)都 在被提出的时候加上了 zxid。实现中 zxid 是一个 64 位的 数字,它高 32 位是 epoch(ZAB 协议通过 epoch 编号来 区分 Leader 周期变化的策略)用来标识 leader 关系是否 改变,每次一个 leader 被选出来,它都会有一个新的 epoch=(原来的 epoch+1),标识当前属于那个 leader 的 统治时期。低 32 位用于递增计数。
6. zookeeper的leader选举
leader选举分为2种;1、服务启动时;2、服务运行时
a) 服务启动时leader选举
每个节点启动时,都是处于LOOKING状态;
具体选举过程如下:
1) 每个 Server 发出一个投票。由于是初始情况,Server1 
和 Server2 都会将自己作为 Leader 服务器来进行投 票,每次投票会包含所推举的服务器的 myid 和 ZXID、 epoch,使用(myid, ZXID,epoch)来表示,此时 Server1 的投票为(1, 0),Server2 的投票为(2, 0),然后各自将 这个投票发给集群中其他机器。
2) 接受来自各个服务器的投票。集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票(epoch)、是否来自 LOOKING 状态的服务器。
3) 处理投票。针对每一个投票,服务器都需要将别人的 投票和自己的投票进行PK,PK规则如下 

i. 优先检查 ZXID。ZXID 比较大的服务器优先作为 Leader 
ii. 如果 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。 

b) 运行过程中的leader选举
当集群leader宕机时,整个集群无法给外部提供服务;选举的过程与启动时大致一致。
1) 变更状态。Leader 挂后,余下的非 Observer 服务器 都会将自己的服务器状态变更为 LOOKING,然后开 始进入 Leader 选举过程。
2) 每个 Server 会发出一个投票。在运行期间,每个服务 器上的 ZXID 可能不同,此时假定 Server1 的 ZXID 为 123,Server3 的 ZXID 为 122;在第一轮投票中,Server1 和 Server3 都会投自己,产生投票(1, 123),(3, 122), 然后各自将投票发送给集群中所有机器。接收来自各 个服务器的投票。与启动时过程相同。
3) 处理投票。与启动时过程相同,此时,Server1 将会成为 Leader。
4) 统计投票。与启动时过程相同。
5) 改变服务器的状态。与启动时过程相同
7. 选举过程源码
自行下载源码查阅;(主函数入口:QUORUMPEERMAIN)
8. 探讨
基于zookeeper的高性能和高可用中间件,我们根据Znode特性和watcher机制可以为我们的配置中心、分布式调度任务、分布式锁做些什么?

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值