前言

可以自行去学习一下Zookeeper中的系统模型,节点特性,权限认证以及事件通知Watcher机制相关知识,本篇主要学习Zookeeper一致性算法和满足分布式协调的Zab协议

Paxos算法

Paxos算法是莱斯利*兰伯特在1990年提出的一种基于消息传递并且具有高度容错特性的一致性算法,是目前公认的解决分布式问题上最有效的算法之一

拜占庭问题

1982年 ,Lamport与另两人共同发表了论文提出了一种计算机容错理论,为了描述这个理论中的问题,假设了一个问题相关的故事场景,如下:

拜占庭帝国有许多支军队,不同军队的将军之间必须制订一个统一的行动计划,从而做出进攻或者撤退的决定,同时,各个将军在地理上都是被分隔开来的,只能依靠军队的通讯员来进行通讯。然而,在所有的通讯员中可能会存在叛徒,这些叛徒可以任意篡改消息,从而达到欺骗将军的目的。

这就是著名的拜占庭问题,而这个问题就和分布式场景下异步系统和不可靠的协议中达到一致性类似,后来Lamport 在 1990年提出了一个理论上的一致性解决方案,茼时给出了严格的数学证明,Paxos算法由此而生。

Paxos算法

我们首先来看一下,对于一个一致性算法来说,我们应该满足哪几点:

1.所有提出的提案最终只有一个被选定

2.如果没有提案,那么最终没有任何选定的提案

3.当提案被选定后,所有客户端都应该能获取到提案信息

在Paxos算法中,有Proposer、Acceptor以及Learner三种角色,彼此之间通过收发消息来实现通信。在分布式场景下,Acceptor绝不可能只有一个实例存在,防止出现单机故障,因此我们需要满足,多个Acceptor的情况下完成选举操作,因此我们可以指定Proposer都向一个Acceptor集合中发送提案,而这个集合中的所有的Acceptor都可能批准提案,当有足够多的Acceptor批准提案的时候,我们就认为这个提案被选定,而所谓的足够多,只需要满足当前Acceptor集合中的大半Acceptor批准提案即可,并且我们规定每个Acceptor在一次选举过程中,只可以批准一个提案。

算法过程

整个Paxos算法的过程可以总结为两阶段提交的算法执行过程,分为Prepare请求阶段Accept请求阶段,大体的过程如下:

Prepare阶段:

Proposer会选择一个提案,并且编号为M0,然后向Acceptor集合中发送M0编号的Prepare请求,如果这个时候Acceptor集合中的某个Acceptor收到了这个请求,并且编号M0比当前已经相应的所有的提案的最大编号还要大,那么Acceptor就需要反馈自己处理的最大编号,并且不会再去响应低于M0编号的任何请求。如果没有响应过请求,则会直接响应当前的M0编号的请求。

Accept阶段:

同样的,当Proposer发出的提案请求收到了来自整个Acceptor集合中的过半Acceptor的响应,那么就代表该提案可以生成,这个时候如果响应中过半是无任何提案信息的,则代表当前的提案的取值可以是任意值,如果响应中过半是其他的提案信息,那么则从中找到最大编号的提案的值,这里称为V0,组成[M0,V0]Acceptor请求,再次发送给整个Acceptor集合。这个时候Acceptor如果没有通过大于v4sp  编号的提案,那么则会视为自动同意该提案,同样如果得到了过半数的同意,则当前提案视为通过。

当然在整个过程中,每个Proposer都有自己的周期定时生成不同的提案,并且严格按照上述过程运行,最终一定能保证算法的正确性,同样的,如果Proposer已经要生成更大编号的提案,Accept将收到的最大的编号信息通知给上一个同意的最大提案的Proposer,让其放弃自己的提案,选择最新的最大编号的提案即可。

Zab协议

看了前面的Paxos算法,我们可能会认为Zookeeper就是基于Paxos算法的实现,但是事实上,Zookeeper并不是完全采用的Paxos,而是一种名为Zookeeper Atomic Broadcast,简称ZAB协议的一种支持奔溃恢复的协议作为数据一致性核心算法。ZAB协议定义整个Zookeeper中关于事物消息的处理流程,大致如下:

所有的Zookeeper处理的事物请求必须仅有一个机器来协调处理,这样的机器被称之为Leader服务器,而剩下的其他Zookeeper则称之为Follower,而Leader服务器则是会将客户端的事物请求发给所有的Follwer服务器,等待所有的Follwer服务器的反馈,一旦接受到了超过半数的Follwer服务器的正常完成事物处理的反馈后,Leader服务器就会再次发送一个Commit消息给所有的Follwer服务器,要求将刚刚的事物请求进行提交

而ZAB协议有两种基本的模式,分别为崩溃恢复消息广播。当整个框架在运行的过程中,或者是当Leader出现网络中断、崩溃重启等异常的情况的时候,ZAB协议就会进入恢复模式,来重新选举一个新的Leader服务器来处理事物请求,当新的Leader服务器选择出来,并且和过半以上的机器实现了状态同步后,ZAB的恢复模式就结束了。这个时候就可以进行ZAB的消息广播模式了,如果在这个过程中有一个新的Zookeeper加入了当前的集群中,就会启动恢复模式,直到实现了和Leader的状态同步为止。

正如上述事物处理的过程一样,Zookeeper中只有Leader可以协调处理事物请求,那么其他的Follower服务器是不是没用了呢?当然不是,在整个Zookeeper集群中,所有的服务器都可以提供对外的请求处理,唯一的区别在于,当Follower服务器接受到了事物请求以后,会转发给Leader,让Leader进行统一处理和协调而已。当然在整个集群的运行过程中会出现很多意外,例如有半数以上的Follower服务器无法与Leader进行正常通信,就会从消息广播模式进入到崩溃恢复模式,从其他的机器中选举一个新的Leader出来,同样的一个Leader的选举必须得到超过半数的机器的支持,所以当整个集群的正常服务的机器超过半数,都可以不停的模式转换,保证集群服务的稳定性,一旦出现问题的机器数量超过了集群的半数,整个集群就不再对外提供事物请求的处理,进入保护模式,仅仅可读。

消息广播

ZAB协议中的消息广播使用的是一个原子广播协议,整体的过程可以看为是一个二阶段提交的过程。客户端的事物请求到来以后,Leader服务器会生成对应的事物Proposal,并且将这个发送给当前集群范围内的其余的所有的机器,并且收集来自所有Follower机器的响应选票信息,而二阶段的过程的具体体现,移除了传统二阶段的中断逻辑处理,因此在收集所有Follower机器的响应过程中,Leader不需要等待所有机器响应后才执行第二阶段,而是只需要等待半数以上的机器返回对应的响应,即可开启第二阶段。当然在这种简化的二阶段过程中,有可能会因为Leader突然奔溃,导致数据不一致的情况,当然出现这种情况就需要启动崩溃恢复机制来处理,并且所有的消息都是具有FIFO特性的TCP协议来进行网络通信的,从而保证消息广播过程中的顺序性。

而在第一阶段,Leader机器会将事物消息生成对应的Proposal进行广播,并且会生成一个单调递增的ID,作为事物的ID(ZXID),由于ZAB协议需要保证事物严格的上下顺序性,所以会严格按照ZXID的先后来处理对应的消息。而在消息广播发起后,Leader会为每一个Follower服务器分配一个单独的队列,然后将需要广播出去的事物Proposal依次存放进这个FIFO的队列中,每个Follower机器收到事物消息后,会按照事物日志的方式写入,成功后反馈给Leader机器Ack响应,当收到半数以上的Ack响应后,Leader就会发起第二阶段的Commit消息给所有的Follower机器,并且这个时候Leader也会和Follower一样进行本地事物的提交操作,完成整个消息的传递和提交

崩溃恢复

前面我们提到过,崩溃恢复机制保障了Leader机器在突然异常的情况下,依然能保障一个事物如果在一台机器上处理成功,那么就应该被所有的机器处理成功。因此ZAB协议的崩溃恢复机制整体需要保障以下两点:

1.所有已经在Leader服务器上提交成功的事物最终要被所有的服务器提交

2.如果Leader在消息广播的第一阶段提出的消息,但是并没有提交,ZAB需要保证丢弃掉这部分事物消息

因此ZAB协议必须设计一个选举算法,保证提交已经被Leader提交的Proposal,同时跳过仅仅是Leader发起的没有提交需要跳过的事物Proposal。所以为了设计选举出来的Leader是拥有集群内机器的最高编号(ZXID最大),那么就可以认为选举出来的Leader有所有已经被提交的提案。

在完成了选举以后,崩溃恢复过程还未结束,此时进入了数据同步过程,Leader需要确认事物日志中的所有的Proposal被过半以上的Follower提交了,才算完成数据同步。前面我们知道Leader服务器会将所有的Follower准备一个FIFO的队列,将所有的需要提交的事物存进去,并且通知Follower,当队列里面所有的日志都已经被Follower提交清空,这个时候代表数据同步完成,该Follower会被加入到可用机器的列表中,直到列表中的可用机器数过半,就会直接开始完成崩溃恢复过程,转换模式为消息广播,对外提供Zookeeper服务。

同样的,Leader中的已经提交的事物完成同步了,那么未提交的废弃事物怎么剔除呢?在ZAB协议的事物编号ZXID设计中,是一个64位的数字,整体分为低32位和高32位,低32位可以看成一个单调递增的计数器,每一个事物消息生成ID前,低32位都会进行原子的+1操作。而ZXID的高32位代表了epoch的编号,而epoch则是每一次选举出新的Leader的过程中,会从所有的事物ZXID中获取最大的,然后解析出对应的高32位epoch的值,然后将其+1,代表了选举的次数,即Leader的生命周期,并且每一次选举后,epoch+1以后,会将低32位的值清零,作为新的ZXID值。因此当选举触发过程中,有部分机器的ZXID所代表的epoch值较低的时候,这些机器直接会成为Follower,只会有epoch最大并且一样的机器之间进行选举出Leader,而当Leader选举出来以后,所有的Follower连接上Leader以后,会和Leader比较当前最大的Proposal,这个时候Leader根据比较情况要求回滚或者同步Proposal到当前集群中过半机器都提交的最大事物Proposal,至此数据同步操作完成,崩溃恢复模式结束。

Zookeeper协议篇-Paxos算法与ZAB协议的更多相关文章

  1. ZAB协议与Paxos算法

    ZooKeeper并没有直接采用Paxos算法,而是采用一种被称为ZAB(ZooKeeper Atomic Broadcast)的一致性协议 ZooKeeper是一个典型的分布式数据一致性的解决方案, ...

  2. 分布式技术专题-分布式协议算法-带你彻底认识Paxos算法、Zab协议和Raft协议的原理和本质

    内容简介指南 Paxo算法指南 Zab算法指南 Raft算法指南 Paxo算法指南 Paxos算法的背景 [Paxos算法]是莱斯利·兰伯特(Leslie Lamport)1990年提出的一种基于消息 ...

  3. 一致性协议之Paxos算法

    一.算法提出背景 Paxos算法需要解决的问题就是如何在一个可能发生诸如宕机或网络异常情况的分布式气筒中,快速且正确地在集群内部对某个数据的值达成一致,并且保证不论发生以上任何异常,都不会破坏整个系统 ...

  4. zookeeper数据一致性与paxos算法

    数据一致性与paxos算法 据说Paxos算法的难理解与算法的知名度一样令人敬仰,所以我们先看如何保持数据的一致性,这里有个原则就是: 在一个分布式数据库系统中,如果各节点的初始状态一致,每个节点都执 ...

  5. 网络基础之网络协议篇---CS架构--网络通信--osi 协议---套接字socket--粘包

    1 C\S 客户端/服务器架构: .硬件 C/S架构 (打印机) .软件 C/S 架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务 ...

  6. 网络编程网络协议篇(osi七层协议)

    一 互联网的本质 咱们先不说互联网是如何通信的(发送数据,文件等),先用一个经典的例子,给大家说明什么是互联网通信. 现在追溯到八九十年代,当时电话刚刚兴起,还没有手机的概念,只是有线电话,那么此时你 ...

  7. 分布式一致性协议之:Zab(Zookeeper的分布式一致性算法)

    Zookeeper使用了一种称为Zab(Zookeeper Atomic Broadcast)的协议作为其一致性复制的核心,据其作者说这是一种新发算法,其特点是充分考虑了Yahoo的具体情况:高吞吐量 ...

  8. zookeeper的ZAB协议

    ZAB协议概述 ZooKeeper并没有完全采用Paxos算法,而是使用了一种称为ZooKeeper Atomic Broadcast(ZAB,zookeeper原子消息广播协议)的协议作为其数据一致 ...

  9. 三:ZooKeeper的ZAB协议

    一:ZAB协议概述--->ZooKeeper并没有完全采用Paxos算法,而是使用了一种称为ZooKeeper Atomic Broadcast(ZAB,zookeeper原子消息广播协议)的协 ...

随机推荐

  1. day26:装饰器

    装饰器 1.装饰器 : 为原函数去扩展新功能,用新函数去替换旧函数 2.作用 : 在不改变原代码的前提下,实现功能上的扩展 3.符号 : @(语法糖) 1.装饰器的基本用法 # 1.装饰器的基本用法 ...

  2. 【MySQL】如何最大程度防止人为误操作MySQL数据库?这次我懂了!!

    写在前面 今天,一位哥们打电话来问我说误操作了他们公司数据库中的数据,如何恢复.他原本的想法是登录数据库update一个记录,结果忘了加where条件,于是悲剧发生了.今天,我们不讲如何恢复误操作的数 ...

  3. Visual-platform,基于Vue的可视化大屏开发GUI框架

    visual-platform 基于Vue的可视化大屏开发GUI框架 ------ CreatedBy 漆黑小T 构建用于开发可视化大屏项目的自适应布局的GUI框架. github仓库: https: ...

  4. 安装黑苹果MoJave记录

    说实话安装黑苹果并不是一件很简单的事情,它既费时,而且还需要一定的计算机知识,最重要的是对于你来说可能黑苹果并没有Linux或者Windows好用. 好了废话不多说,开始吧. 1.硬件准备 并不是什么 ...

  5. Mybatis-02-CRUD及配置解析

    CRUD 1.namespace namespace中的包名要和Dao/Mapper接口的包名一致! 2.select 选择,查询语句; id:对应的namespace中的方法名 resultType ...

  6. PYTHON-错误-函数有返回值未接收导致替换不成功

    #1.有返回值,没有赋值,替换不成功 cxj = 'guapi' cxj.replace(cxj,'2b') print(cxj) #2.有返回值,赋值,替换成功 cxj = 'guapi' cxj ...

  7. 旧 WCF 项目成功迁移到 asp.net core web api

    背景 接上一篇,放弃了 asp.net core + gRPC 的方案后,我灵光一闪,为什么不用 web api 呢?不也是 asp.net core 的吗?虽然 RESTful 不是强约束,客户端写 ...

  8. Java并发编程(07):Fork/Join框架机制详解

    本文源码:GitHub·点这里 || GitEE·点这里 一.Fork/Join框架 Java提供Fork/Join框架用于并行执行任务,核心的思想就是将一个大任务切分成多个小任务,然后汇总每个小任务 ...

  9. 在GitHub上删除仓库 or 项目,基操!!

    创建错误或者想要抛弃某个仓库or项目,点击选择项目,选择Setting页面,左侧方框Option页拉到底: 你就可以看到一个红色的危险域,called Danger Zone,这不禁让我想到了黑子篮球 ...

  10. 全网最通透的Java8版本特性讲解

    「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...