zookeeper 理论基础-Paxos算法深入讲解,ZAB协议讲解,CAP定理讲解

1.zookeeper是什么

官方文档上这么解释zookeeper,它是一个分布式服务框架,是Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。

2. 如何保证一致性

zk的一致性提现在一下几方面:

  • 顺序一致性(同一客户端发起的事务请求会严格按照请请求顺序执行)
  • 原子性
  • 单一视图(从集群任意一个节点读取的数据一致)
  • 可靠性
  • 最终一致性(向节点A增加数据,B会延迟加载数据,最终会保证最终一致性)

3.Zookeeper和Paxos算法关系

Paxos算法是Zookeeper实现的基础,有一篇文章标题更是以“Zookeeper全解析——Paxos作为灵魂” 作为标题,里面解析的更透彻

4. Paxos算法

4.1 算法简介

Paxos算法是莱斯利·兰伯特(Leslie Lamport,就是 LaTeX中的"La",此人现在在微软研究院)于1990年提出的一种基于消息传递的一致性算法。这个算法被认为是类似算法中最有效的。

4.2 算法解决问题

Paxos算法解决的问题是一个分布式系统如何就某个值(决议)达成一致。一个典型的场景是,在一个分布式数据库系统中,如果各节点的初始状态一致,每个节点执行相同的操作序列,那么他们最后能得到一个一致的状态。为保证每个节点执行相同的命令序列,需要在每一条指令上执行一个“一致性算法”以保证每个节点看到的指令一致。一个通用的一致性算法可以应用在许多场景中,是分布式计算中的重要问题。因此从20世纪80年代起对于一致性算法的研究就没有停止过。节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing)。Paxos 算法就是一种基于消息传递模型的一致性算法

4.3 Paxos与拜占庭将军问题

占庭将军问题含义是在存在消息丢失的不可靠信道上试图通过消息传递的方式达到一致性是不可能的。因此Paxos算法的前提下是 拜占庭将军问题不存在

4.4 算法描述

4.4.1 三种角色

在Paxos算法中有三种角色,分别对应着三种不同的行为,但在很多时候,一个进程可能同时充当着多种角色

  • Proposer:提案(Proposal)的提议者。在一个集群中 提议者(Proposer)也是会存在多个的,每一个提议者会提出不同提案。
  • Acceptor:提案的表决者,作用是 是否通过(Accept)该提案 。超过半数的表决者(Acceptor)接受该提案(Proposer),那么该提案者被认定为 选定
  • Learners:提案的学习者。当提案别选定时,其要执行提案内容

4.4.2 Paxos 算法的一致性

​ Paxos算法的一致性主要体现在以下几点:

  • 没有提案被提出则不会有提案被选定

  • 每一个提议者在提出提案是首先都会获取一个具有唯一性且递增的提案编号N。然后该编号会被赋予其要提出的提案。

  • 每一个表决者在通过(Accept)提案之后 ,会将该提案的编号N 记录在本地。这样每一个表决者中保存的已经被通过(Accept)的提案中会存在一个编号最大的提案,假设其为maxN。每一个表决者只会通过比自己本地maxN大的提案。

  • 在众多提案中有且仅有一个提案被选定。

  • 一旦一个提案被选定,其他服务器会主动同步(Learn)改提案到本地

4.4.3 算法过程描述

paxos算法的执行分为两个阶段:准备阶段( prepare) 和 接受阶段(accept)

A. prepare阶段

  • 提议者准备提交一个编号为N的提议,首先向表决者发送一个proposal(N)的请求,用于试探集群是否支持该编号的提案。

  • 每一个表决者会保存自己曾通过的提案中最大的编号maxN,当表决者收到提案者发送过来的请求时,会比较 proposal(N) 和自己保存的maxN,会有以下几种情况

    1. maxN>N:表明提案已过时,表决者不回应或者回应Error来表示拒绝该提案。

    2. maxN<N:则表示该提案可以接受。当前表决者会将N记录下来。并将其曾经已经通过的最大编号的提案proposal(myid,maxN,value)返回给提议者,

      1. myid:当前表决者标示Id
      2. maxN:当前表决者通过提案中最大的编号
      3. value:maxN对应提案的内容

      若当前表决者还未通过任何提案,则会返回proposal(myid,null,null)

B. accept 阶段

  • 当提案者发送出提案proposal(N)后,如果收到超过半数的表决者的反馈,那么该提议者就会将其真正的提案proposal(myid,maxN,value)发送给全部的表决者
  • 当表决者收到提案者发送的提案proposal(myid,maxN,value)后,会再次拿出自己的maxN,或曾经记录下的收到尚未执行proposal(N),让他们比较,若N>=maxN,N 则表示通过该提案,并做出反馈,若N<maxN,N,则返回error 或者不返回信息 来拒绝天
  • 若提案者收到少于半数决策者的反馈,那么提案者会再次进入prepare状态,递增提案号,再次发起prepare请求
  • 若提案者收到大于半数决策者的反馈,则会向外广播两类信息
    • 向曾经接收到提案的决策者发送 “可执行数据同步信号”,让他们执行其曾接受到的天
    • 向未收到天的决策者发送,“提案+可执行数据同步信号”,让他们收到提案后立即执行

4.5 paxos活锁问题

有很多算法对paxos算法进行了改进,比如 fast paxos ,EPaxos,Multi Paxos等
例如 paxos算法中存在 “活锁问题” ,Fast Paxos 算法进行了改进:只允许一个进程处理写请求(其具有对N的唯一操作权),解决了活锁问题

5. ZAB协议

5.1 ZAB 协议简介

ZAB ,Zookeeper Atomic Broadcast,zk 原子消息广播协议,是专为 ZooKeeper 设计的一 种支持崩溃恢复的原子广播协议,在 Zookeeper 中,主要依赖 ZAB 协议来实现分布式数据 一致性。 Zookeeper 使用一个单一主进程来接收并处理客户端的所有事务请求,即写请求。当服 务器数据的状态发生变更后,集群采用 ZAB 原子广播协议,以事务提案 Proposal 的形式广 播到所有的副本进程上。ZAB 协议能够保证一个全局的变更序列,即可以为每一个事务分配 一个全局的递增编号 xid。 当 Zookeeper 客户端连接到 Zookeeper 集群的一个节点后,若客户端提交的是读请求, 那么当前节点就直接根据自己保存的数据对其进行响应;如果是写请求且当前节点不是 Leader,那么节点就会将该写请求转发给 Leader,Leader 会以提案的方式广播该写操作,只 要有超过半数节点同意该写操作,则该写操作请求就会被提交。然后 Leader 会再次广播给 所有订阅者,即 Learner,通知它们同步数据。

5.2 ZAB 与 Paxos 的关系

​ ZAB 协议是 Fast Paxos 算法的一种工业实现算法。但两者的设计目标不太一样。ZAB 协 议主要用于构建一个高可用的分布式数据主备系统,例如,Leader 挂了,马上就可以选举出 一个新的 Leader。而 Paxos 算法则是用于构建一个分布式一致性状态机系统,确保系统中各 个节点的状态都是一致的。 另外,ZAB 还使用 Google 的 Chubby 算法作为分布式锁的实现,而 Google 的 Chubby 也 是 Paxos 算法的应用。

5.3 三类角色

​ 为了避免 Zookeeper 的单点问题,zk 也是以集群的形式出现的。zk 集群中的角色主要有 以下三类:

  • Leader:集群中事务请求的唯一处理者,其还负责进行投票及决议。
  • Follower:可以接收客户端读/写请求,可以响应读请求,可以将写请求转发给 Leader。 当 Leader 宕机后,其还具有新 Leader 的选举权与被选举权。
  • Observer:就是一个没有选举权与被选举权的 Follower。

​ 这三类角色在不同的情况下又有一些不同的叫法。

  • Learner = Follower + Observer
  • QuorumServer = Leader + Follower

5.4 三个数据

​ 在 ZAB 中有三个很重要的数据:

  • zxid:64 位长度的 Long,高 32 位是 epoch,低 32 位是 xid。zxid = epoch + xid
  • epoch
  • xid

5.5 三种模式

​ ZAB 协议中对 zkServer 的状态描述有三种模式。这三种模式并没有十分明显的界线,它 们相互交织在一起。

  • 恢复模式:Leader 的选举阶段,与初始化同步阶段。
  • 广播模式:初始化广播,与更新广播。
  • 同步模式:初始化同步,与更新同步。

5.6 同步模式和广播模式

1. 初始化同步

​ 前面我们说过,恢复模式具有两个阶段:Leader 选举与初始化同步。当完成 Leader 选 举后,此时的 Leader 还是一个准 Leader,其要经过初始化同步后才能变为真正的 Leader。

​ 具体过程如下:

  1. 为了保证 Leader 向 Learner 发送提案的有序,Leader 会为每一个 Learner 服务器准备一 个队列
  2. Leader 将那些没有被各个 Learner 同步的事务封装为 Proposal
  3. Leader 将这些 Proposal 逐条发给各个 Learner,并在每一个 Proposal 后都紧跟一个 COMMIT 消息,表示该事务已经被提交,Learner 可以直接接收并执行
  4. Learner 接收来自于 Leader 的 Proposal,并将其更新到本地
  5. 当 Follower 更新成功后,会向准 Leader 发送 ACK 信息
  6. Leader 服务器在收到该来自 Follower 的 ACK 后就会将该 Follower 加入到真正可用的 Follower 列表。没有反馈 ACK,或反馈了但 Leader 没有收到的 Follower,Leader 不会将 其加入到 Follower 列表。

2. 消息广播算法

​ 当集群中已经有过半的 Follower 完成了初始化状态同步,那么整个 zk 集群就进入到了 正常工作模式了。

如果集群中的其他节点收到客户端的事务请求,那么这些 Learner 会将请求转发给 Leader 服务器。然后再执行如下的具体过程:

  1. Leader 接收到事务请求后,为事务赋予一个全局唯一的 64 位自增 id,即 zxid,通过 zxid 的大小比较即可实现事务的有序性管理,然后将事务封装为一个 Proposal。
  2. Leader 根据 Follower 列表获取到所有 Follower,然后再将 Proposal 通过这些 Follower 的 队列将提案发送给各个 Follower。
  3. 当 Follower 接收到提案后,会先将提案的 zxid 与本地记录的事务日志中的最大的 zxid 进行比较。若当前提案的 zxid 大于最大 zxid,则将当前提案记录到本地事务日志中,并 向 Leader 返回一个 ACK。
  4. 当 Leader 接收到过半的 ACKs 后,Leader 就会向所有 Follower 的队列发送 COMMIT 消息,向所有 Observer 的队列发送 Proposal。
  5. 当 Follower 收到 COMMIT 消息后,就会将日志中的事务正式更新到本地。当 Observer 收到 Proposal 后,会直接将事务更新到本地。

5.7 恢复模式的两个原则

1. 已被处理过的消息不能丢

​ 当 Leader 收到超过半数 Follower 的 ACKs 后,就向各个 Follower 广播 COMMIT 消息, 批准各个 Server 执行该写操作事务。当各个 Server 在接收到 Leader 的 COMMIT 消息后就会 在本地执行该写操作,然后会向客户端响应写操作成功。 但是如果在非全部 Follower 收到 COMMIT 消息之前 Leader 就挂了,这将导致一种后 果:部分 Server 已经执行了该事务,而部分 Server 尚未收到 COMMIT 消息,所以其并没有 执行该事务。当新的 Leader 被选举出,集群经过恢复模式后需要保证所有 Server 上都执行 了那些已经被部分 Server 执行过的事务。

2. 被丢弃的消息不能再现

​ 当 Leader 接收到事务请求并生成了 Proposal,但还未向任何 Follower 发送时就挂了, 因此,其他 Follower 根本就不知道该 Proposal 的存在。当新的 Leader 选举出来,整个集群 进入正常服务状态后,之前挂了的 Leader 主机重新启动并注册成为了 Follower。若那个别 人根本不知道的 Proposal 还保留在那个主机,那么其数据就会比其它主机多出了内容,导致 整个系统状态的不一致。所以,该 Proposa 应该被丢弃。类似这样应该被丢弃的事务,是不 能再次出现在集群中的,应该被清除。

5.8 Leader 选举

​ 当集群正在启动过程中,或 Leader 与超过半数的主机断连后,集群就进入了恢复模式。 而恢复模式中最重要的阶段就是 Leader 选举。

1. Leader 选举中的基本概念

  1. myid

    这是 zk 集群中服务器的唯一标识,称为 myid。例如,有三个 zk 服务器,那么编号分别 是 1,2,3。

  2. 逻辑时钟

    逻辑时钟,Logicalclock,是一个整型数,该概念在选举时称为 logicalclock,而在选举结 束后称为 epoch。即 epoch 与 logicalclock 是同一个值,在不同情况下的不同名称。

  3. zk 状态

    zk 集群中的每一台主机,在不同的阶段会处于不同的状态。每一台主机具有四种状态。

    • LOOKING:选举状态
    • FOLLOWING:跟随状态
    • OBSERVING:观察状态
    • LEADING:领导状态

2. Leader 选举算法

在集群启动过程中的 Leader 选举过程(算法)与 Leader 断连后的 Leader 选举过程稍微 有一些区别,基本相同。

  1. 集群启动中的 Leader 选举

    若进行 Leader 选举,则至少需要两台主机,这里以三台主机组成的集群为例。

    在集群初始化阶段,当第一台服务器 Server1 启动时,其会给自己投票,然后发布自己 的投票结果。投票包含所推举的服务器的 myid 和 ZXID,使用(myid, ZXID)来表示,此时 Server1 的投票为(1, 0)。由于其它机器还没有启动所以它收不到反馈信息,Server1 的状态一直属于 Looking,即属于非服务状态。

    1582658285742.png

    1582658285742.png

    ​ 当第二台服务器 Server2 启动时,此时两台机器可以相互通信,每台机器都试图找到 Leader,选举过程如下:

    • 每个 Server 发出一个投票。此时 Server1 的投票为(1, 0),Server2 的投票为(2, 0),然后 各自将这个投票发给集群中其他机器。

    • 接受来自各个服务器的投票。集群的每个服务器收到投票后,首先判断该投票的有效 性,如检查是否是本轮投票、是否来自 LOOKING 状态的服务器。

    • 处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行 PK,PK 规则如下:

      • 优先检查 ZXID。ZXID 比较大的服务器优先作为 Leader。
      • 如果 ZXID 相同,那么就比较 myid。myid 较大的服务器作为 Leader 服务器。

      对于 Server1 而言,它的投票是(1, 0),接收 Server2 的投票为(2, 0)。其首先会比较两者 的 ZXID,均为 0,再比较 myid,此时 Server2 的 myid 最大,于是 Server1 更新自己的投票为 (2, 0),然后重新投票。对于 Server2 而言,其无须更新自己的投票,只是再次向集群中所有 主机发出上一次投票信息即可。

    • 统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到 相同的投票信息。对于 Server1、Server2 而言,都统计出集群中已经有两台主机接受了(2, 0) 的投票信息,此时便认为已经选出了新的 Leader,即 Server2

    • 改变服务器状态。一旦确定了 Leader,每个服务器就会更新自己的状态,如果是 Follower,那么就变更为 FOLLOWING,如果是 Leader,就变更为 LEADING。

    • 添加主机。在新的 Leader 选举出来后 Server3 启动,其想发出新一轮的选举。但由于 当前集群中各个主机的状态并不是 LOOKING,而是各司其职的正常服务,所以其只能是以 Follower 的身份加入到集群中。

  2. 断连后的 Leader 选举
    在 Zookeeper 运行期间,Leader 与非 Leader 服务器各司其职,即便当有非 Leader 服务 器宕机或新加入时也不会影响 Leader。但是若 Leader 服务器挂了,那么整个集群将暂停对 外服务,进入新一轮的 Leader 选举,其过程和启动时期的 Leader 选举过程基本一致。
    sss

    sss


    假设正在运行的有 Server1、Server2、Server3 三台服务器,当前 Leader 是 Server2,若 某一时刻 Server2 挂了,此时便开始新一轮的 Leader 选举了。选举过程如下:
  • 变更状态。Leader 挂后,余下的非 Observer 服务器都会将自己的服务器状态由FOLLOWING 变更为 LOOKING,然后开始进入 Leader 选举过程
  • 每个 Server 会发出一个投票,仍然会首先投自己。不过,在运行期间每个服务器上 的 ZXID 可能是不同,此时假定 Server1 的 ZXID 为 111,Server3 的 ZXID 为 333;在第一轮投 票中,Server1 和 Server3 都会投自己,产生投票(1, 111),(3, 333),然后各自将投票发送给 集群中所有机器。
  • 接收来自各个服务器的投票。与启动时过程相同。集群的每个服务器收到投票后, 首先判断该投票的有效性,如检查是否是本轮投票、是否来自 LOOKING 状态的服务器。
  • 处理投票。与启动时过程相同。针对每一个投票,服务器都需要将别人的投票和自 己的投票进行 PK。对于 Server1 而言,它的投票是(1, 111),接收 Server3 的投票为(3, 333)。 其首先会比较两者的 ZXID,Server3 投票的 zxid 为 333 大于 Server1 投票的 zxid 的 111,于是 Server1 更新自己的投票为(3, 333),然后重新投票。对于 Server3 而言,其无须更新自己的投 票,只是再次向集群中所有主机发出上一次投票信息即可。
  • 统计投票。与启动时过程相同。对于 Server1、Server2 而言,都统计出集群中已经 有两台主机接受了(3, 333)的投票信息,此时便认为已经选出了新的 Leader,即 Server3。
  • 改变服务器的状态。与启动时过程相同。一旦确定了 Leader,每个服务器就会更新 自己的状态。Server1 变更为 FOLLOWING,Server3 变更为 LEADING。

6. CAP 定理

6.1 简介

​ CAP 原则又称 CAP 定理,指的是在一个分布式系统中,Consistency(一致性)、Availability (可用性)、Partition tolerance(分区容错性),三者不可兼得。

  • 一致性(C):分布式系统中多个主机之间是否能够保持数据一致的特性。即,当系统数 据发生更新操作后,各个主机中的数据仍然处于一致的状态。
  • 可用性(A):系统提供的服务必须一直处于可用的状态,即对于用户的每一个请求,系 统总是可以在有限的时间内对用户做出响应
  • 分区容错性(P):分布式系统在遇到任何网络分区故障时,仍能够保证对外提供满足一 致性和可用性的服务。

6.2 三二原则

​ 对于分布式系统,网络环境相对是不可控的,出现网络分区是不可避免的,因此系统必 须具备分区容错性。但其并不能同时保证一致性与可用性。CAP 原则对于一个分布式系统来 说,只可能满足两项,即要么 CP,要么 AP。这就是 CAP 的三二原则。

6.3 BASE 理论

​ BASE 是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent(最 终一致性)三个短语的简写

​ BASE 理论的核心思想是:即使无法做到强一致性,但每个系统都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性。

  1. 基本可用

    基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性。

  2. 软状态
    软状态,是指允许系统数据存在的中间状态,并认为该中间状态的存在不会影响系统的 整体可用性,即允许系统主机间进行数据同步的过程存在一定延时。软状态,其实就是一种 灰度状态,过渡状态。

  3. 最终一致性
    最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到 一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需 要实时保证系统数据的强一致性。
    在没有发生故障的前提下,数据达到一致状态的时间延迟,取决于网络延迟,系统负载 和数据复制方案设计等因素。

6.4 ZK 与 CP

​ zk 遵循的是 CP 原则,即保证了一致性,但牺牲了可用性。体现在哪里呢?

​ 当 Leader 宕机后,zk 集群会马上进行新的 Leader 的选举。但选举时长在 30-200 毫秒间, 整个选举期间 zk 集群是不接受客户端的读写操作的,即 zk 集群是处于瘫痪状态的。所以, 其不满足可用性

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值