分布式协调框架_Zookeeper

 

Zookeeper 现在在分布式架构中应用十分普遍,它做为分布式协调框架在分布式架构中有着举足轻重的地位,本文是主要从以上几个方面对 Zookeeper 经常使用的知识进行总结。node

 

一 从集中式到分布式架构的演变算法

 

架构的演变过程在以前的文章《浅谈网站架构演变》中有所介绍数据库

 

分布式服务架构:服务器

 

 

 

分布式架构:由多台机器经过网络通讯组成,分布式的故障发生频率大。 
故障缘由:网络问题,多台机器网络通讯容易超时,中间有可能断掉形成分区。 
网络分区:俗称脑裂。 
网络的三态问题:要么链接成功,要么失败,要么超时。网络

因此分布式主要是网络方面和机器方面的问题,最大问题是网络问题。session

 

传统ACID 、 CAP理论、BASE理论架构

传统的集中式架构的事务讨论的是 ACID :并发

原子性:要么成功,要么失败; 
一致性:若是出现异常数据,仍是原来的那份 
隔离性:各个会话之间是相互独立的 
持久性:就是提交后的数据永久保存在磁盘上,不丢失。负载均衡

CAP理论

Consistency,Availability和Partition Tolerance,即CAP。框架

 

(C) 一致性:多台机器拥有相同副本 
(A) 可用性:在适合的时间响应客户端 
(P) 分区容错性:不能出现网络分区

CAP在分布式架构中是不能都具有的,只能选择两种特性,而因为分布式架构都是集群部署的,因此分区容错性(P)是必需要的,可用性(A)、一致性(C)根据架构不一样选择的状况也不一样,Zookeeper 是CP 模型,也就是说 Zookeeper 在集群出现问题时不会保证可用性,而是会牺牲部分对外服务时间,它保证的是数据的强一致性。

BASE理论

分布式主要的问题是网络问题,因此咱们优先处理分布式的网络问题,而后在一致性和可用性之间权衡。这时提出了 BASE 就是对 CAP 的一致性和可用性的权衡结果。 

BASE 也叫基本可用,也就是最终一致性原则

最终一致性:就是你提交一台机器,在必定时间内,数据会不一致,其余机器最终会把你提交的那台机器给同步到本身上,数据会最终一致。

 

二 分布式事务、2PC、3PC 、Paxos

 

数据不一致问题

在分布式架构数据有多副本的状况下,若是网络、服务器或者软件出现故障,会致使部分副本写入成功,部分副本写入失败。这就形成各个副本之间的数据不一致,数据内容冲突,形成事实上的数据不一致。

 

2PC

 

两阶段提交协议是协调全部分布式原子事务参与者,并决定提交或取消(回滚)的分布式算法。

 

  • 协议参与者

 

在两阶段提交协议中,系统通常包含两类机器(或节点):一类为协调者(coordinator),一般一个系统中只有一个;另外一类为事务参与者(participants,cohorts 或 workers),通常包含多个,在数据存储系统中能够理解为数据副本的个数。

 

协议中假设每一个节点都会记录写前日志(write-ahead log)并持久性存储,即便节点发生故障日志也不会丢失。协议中同时假设节点不会发生永久性故障并且任意两个节点均可以互相通讯。

 

  • 两个阶段的执行

 

1.请求阶段(commit-request phase,或称表决阶段,voting phase)

 

在请求阶段,协调者将通知事务参与者准备提交或取消事务,而后进入表决过程。

 

在表决过程当中,参与者将告知协调者本身的决策:赞成(事务参与者本地做业执行成功)或取消(本地做业执行故障)。

 

2.提交阶段(commit phase)

 

在该阶段,协调者将基于第一个阶段的投票结果进行决策:提交或取消。

当且仅当全部的参与者赞成提交事务协调者才通知全部的参与者提交事务,不然协调者将通知全部的参与者取消事务。

 

参与者在接收到协调者发来的消息后将执行响应的操做。

 

  • 两阶段提交的缺点

 

1. 同步阻塞问题

 

执行过程当中,全部参与节点都是事务阻塞型的。当参与者占有公共资源时,其余第三方节点访问公共资源不得不处于阻塞状态。

 

2.单点故障

 

因为协调者的重要性,一旦协调者发生故障。参与者会一直阻塞下去。尤为在第二阶段,协调者发生故障,那么全部的参与者还都处于锁定事务资源的状态中,而没法继续完成事务操做。(若是是协调者挂掉,能够从新选举一个协调者,可是没法解决由于协调者宕机致使的参与者处于阻塞状态的问题)

 

3.数据不一致

 

在二阶段提交的阶段二中,当协调者向参与者发送 commit 请求以后,发生了局部网络异常或者在发送 commit 请求过程当中协调者发生了故障,这回致使只有一部分参与者接受到了 commit 请求。

而在这部分参与者接到 commit 请求以后就会执行 commit 操做。可是其余部分未接到 commit 请求的机器则没法执行事务提交。因而整个分布式系统便出现了数据部一致性的现象。

 

  • 两阶段提交没法解决的问题

 

  1. 当协调者出错,同时参与者也出错时,两阶段没法保证事务执行的完整性。

     

  2. 考虑协调者在发出 commit 消息以后宕机,而惟一接收到这条消息的参与者同时也宕机了。那么即便协调者经过选举协议产生了新的协调者,这条参与者事务的状态也是不肯定的,没人知道事务是否被已经提交。

 

3PC

 

三阶段提交协议在协调者和参与者中都引入超时机制,而且把两阶段提交协议的第一个阶段拆分红了两步:询问,而后再锁资源,最后真正提交

 

  • 三个阶段的执行

     

  • CanCommit 阶段


3PC 的 CanCommit 阶段其实和 2PC 的准备阶段很像。
协调者向参与者发送 commit 请求,参与者若是能够提交就返回 Yes 响应,不然返回 No 响应。

 

  • PreCommit 阶段


协调者根据参与者的反应状况来决定是否能够继续事务的 PreCommit 操做。


根据响应状况,有如下两种可能:

 

  1. 假如协调者从全部的参与者得到的反馈都是 Yes 响应,那么就会进行事务的预执行:

     

  •  发送预提交请求。协调者向参与者发送 PreCommit 请求,并进入Prepared 阶段。

  • 事务预提交。参与者接收到 PreCommit 请求后,会执行事务操做,并将 undo 和 redo 信息记录到事务日志中。

  • 响应反馈。若是参与者成功的执行了事务操做,则返回 ACK 响应,同时开始等待最终指令。

 

    2.假若有任何一个参与者向协调者发送了 No 响应,或者等待超时之           后,协调者都没有接到参与者的响应,那么就中断事务:

  • 发送中断请求。协调者向全部参与者发送中断请求。

  • 中断事务。参与者收到来自协调者的中断请求以后(或超时以后,仍未收到中断的请求),执行事务的中断。

 

  • DoCommit 阶段

     

该阶段进行真正的事务提交,也能够分为如下两种状况:

 

  • 执行提交

     

  1. 发送提交请求。协调者接收到参与者发送的 ACK 响应,那么他将从预提交状态进入到提交状态。并向全部参与者发送 doCommit 请求。

  2. 事务提交。参与者接收到 doCommit 请求以后,执行正式的事务提交。并在完成事务提交以后释放全部事务资源。

  3. 响应反馈。事务提交完以后,向者发送 ACK 响应。

  4. 完成事务。协调者接收到全部参与者的 ACK 响应以后,完成事务。

 

  • 中断事务

 

协调者没有接收到参与者发送的ACK响应(多是接受者发送的不是 ACK 响应,也可能响应超时),那么就会执行中断事务。

 

  • 三阶段提交协议和两阶段提交协议的不一样

     

对于协调者(Coordinator)和参与者(Cohort)都设置了超时机制(在 2PC 中,只有协调者拥有超时机制,即若是在必定时间内没有收到参与者的消息则默认失败)。


在 2PC 的准备阶段和提交阶段之间,插入预提交阶段,使 3PC 拥有CanCommit、PreCommit、DoCommit 三个阶段。
PreCommit 是一个缓冲,保证了在最后提交阶段以前各参与节点的状态是一致的。

 

  • 三阶段提交协议的缺点

     

若是进入 PreCommit 后,协调者发出的是中断请求,假设只有一个参与者收到并进行了中断操做;


而其余对于系统状态未知的参与者会根据 3PC 选择继续 Commit,此时系统状态发生不一致性。

 

paxos 半数协议

有个叫 paxos小岛,岛上居民每项决定都得经过提议而后半数才能生效,每一个决定的提议都有一个惟一的全局编号,这个编号只能自增加,不能后退。 


何为经过:就是提议的 id 号要大于议员手记录的最大的 id

第一阶段:提议者发起提议给每一个议员,而后等议员反馈赞成或不一样意。

第二阶段:若是半数以上赞成了,则执行事务,不然不执行。

若是半数以上赞成了,这个议题就经过,而后提议者就命令剩下的议员同步本身的数据,并修改手上的最大 id 号。

问题

在分布式中并发是常见的,例如如今有提议者 p1,p2 
提议者同时提出一个提议,这个时候他们手上的 id 就有多是同样,p1的 id 是3,p2的 id 也是3。当 p1 提议给议员(假设议员手上的 id是 2),如今议员先赞成了 p1,p2 来访问这个议员,议员告诉他已经赞成了议题 id 是 3,p2 的 id 是 3 不一样意。而后p2回去加大本身的 id从新请求,议员这时赞成了他。p1 收到半数赞成准备去通知他们来更新 id 同步数据,但是发现议员们的 id 比本身的大了,而后 p1 又加大 id。这种极端状况,致使死锁了。 


这种解决办法就是提议者只有一个,也就是 paxos 里面说的总统。

三  Zookeeper 简介

 

  • 什么是 Zookeeper

     

     

     

 

Zookeeper 是为了解决分布式一致性问题的工程应用

Zookeeper 并无直接用 paxos 协议,而是在 paxos 协议的基础上,提出了符合本身符合实际应用场景的高可用的一致性协议 --- ZAB 原子广播协议。

Zookeeper 分布式一致性的特色:

  • 顺序一致性:客户端访问 Zookeeper 的一个节点,发起事务,是排着队到 leader 那让他发起提议,一个一个来;

     

  • 单一视图:任何节点上的数据都是同样的,因此客户端访问任意节点都看到是相同的数据。

     

  • 可靠性:给了一个客户端反馈,赞成他的请求,那么就是真的赞成了。

     

  • 实时性:Zookeeper 保证在必定时间内,好比 5 秒以后你能够访问到最新数据。这是最终一致性致使的。

     

    • Zookeeper 设计目标

       

       

       

 

    • 简单的数据模型:就是文件夹的树形结构

       

    • 能够构建集群

       

    • 顺序访问:客户端提出了一个事务请求,会得到一个惟一的id编号,用于操做的前后顺序;

       

    • 高性能:这里指的是读取数据

       

       

  •  Zookeeper的几个角色

     

     

 

Zookeeper有几个角色:leaderfollowerobserver;其中observer 通常不配置,它也不参与投票,observer 能够在不影响写性能的状况下提高集群的读性能; 


Zookeeper 中节点有实体机器节点,还有 znode 数据节点。znode 数据节点指的是目录文件夹。数据节点有永久数据节点和临时节点。

 

  • watcher监听机制

     

     

     

 

Zookeeper 有 watcher 监听机制,例如一个临时数据节点,若是客户session 中断了,临时节点就删除了,这时 watche r就监听到了。这点就是 hadoop 的 HA 实现机制,zkfc 实现了 Zookeeper 的 watcher机制来自动切换。

 

  • Zookeeper的权限

     

 

Zookeeper 的数据节点就是一个文件夹目录,它有本身的权限机制ACL 。 ACL是Access Control Lists 的简写, ZooKeeper 采用 ACL 策略来进行权限控制,有如下权限:

  • CREATE:建立子节点的权限

  • READ:获取节点数据和子节点列表的权限

  • WRITE:更新节点数据的权限

  • DELETE:删除子节点的权限

  • ADMIN:设置节点 ACL 的权限

实际 Zookeeper 删除、设置、建立目录,这些就是执行权限。

 

四  ZAB 原子广播协议

 

  • zab 的三种状态

 

    1. Looking/election : 系统刚启动时或者 Leader 崩溃后正处于选举状态;

    2. Following:Follower 节点所处的状态,Follower 与 Leader 处于数据同步阶段;

    3. Leading:Leader 所处状态,当前集群中有一个 Leader 为主进程。

       

       

  • zab 阶段划分:

 

宏观上来看分为:

 

  • 崩溃恢复阶段

  • 快速选举阶段

  • 原子广播阶段

微观上来看分为:

  • leader 选举阶段

        节点在选举开始读默认投票给本身,当接收其余节点的选票时,会         根据上面的条件更改本身的选票并从新发送选票给其余节点,当一         个节点的获得票超过半数,该节点会设置本身的状态 leading,其         他节点会设置本身的状态为 following。

        成为 leader 的条件: 

 

    1. 选 epoch 最大的; 

       

    2.  epoch 相等,选 zxid 最大的 

       

    3.  epoch和 zxid 都相等,选择 server id最大的(就是配置 zoo.cfg 中的 myid)。

 

那什么是 epoch,什么是 zxid 呢? 

epoch 是 leader 标识,zxid 是事务标识。

epoch 是指:年代,一个领导挂了,另外一个领导上任,如今就是新领导的时代了,当产生新领导,事务编号就从0开始。

zxid是总称:前32位是 leader 编号(epoch),后32位是这个 leader下事务编号。


首先 ZooKeeper 一个事务包含两部分,一个是数据,一个是id;

id是全局惟一的 id,数据就是具体操做数据,而且是 lastid 加1,

ZooKeeper 每一个请求都是顺序执行的,强顺序性的。



  • 发现阶段

     

发现阶段主要是发现最大的 epoch 和最大的事务编号; 


第一阶段快速产生准备 leader,其余节点就是 follower,而后在发现阶段 follower 向 leader报告本身的epoch和事务编号,leader 进行排序,选择最大的 epoch 和最大的事务编号,以后通知 follower 去更改它的 epoch。

 

  • 同步阶段

     

leader 利用上一个阶段知道最大事务编号,而后通知其余 follower 去leader 这同步数据。事务编号有可能不同,因此要同步。保持数据最终一致性。

 

  • 原子广播阶段

这时候 leader 真正对外提供服务,接受客户端的请求,生成一个数据,半数以上赞成,而后就提交事务。剩下的其余节点直接去 leader 那同步数据。

  • 问题:原来挂掉的 leader 的事务怎么处理?

挂掉的 leader 启动起来,发现它的时代已通过时了,就删除事务,发现有新的 leader,本身就变成 follower,而后就去同步数据。

在选举上,会选举拥有最新提议历史( lastzxid最大)的节点做为leader,这样子就省去了发现最新提议的步骤。这是局域拥有最新提议的节点也有最新提交记录的前提。

 

  •  zab 和 paxos 区别与联系

 

ZAB 协议并非 Paxos 算法的一个典型实现,在讲解 ZAB 和 Paxos 之间的区别以前,咱们首先来看下二者的联系。

 

  • 二者都存在一个相似于Leader进程的角色,由其负责协调多个 Follow 进程的运行。

     

  • Leader 进程都会等待超过半数的 Follower 作出正确的反馈后,才会将一个提案进行提交

     

  • 在ZAB协议中,每一个提议中都包含了一个 epoch 值,用来表明当前Leader 周期,在 Paxos 算法中,一样存在这样一个标识,只是名字变成了 Ballot。

  •  

在 Paxos 算法中,一个新选举产生的主进程会进行读和写两个阶段的工做。

 

第一阶段被称为读阶段,在这个阶段中,这个新的主进程会经过和全部其余进程进行通讯的方式来收集上一个主进程的提案,并将他们提交。

 

第二阶段被称为写阶段,在这个阶段,当前主进程开始提出他本身的提案。

 

在Paxos算法设计的基础上,ZAB 协议额外添加了一个同步阶段,ZAB  会进行 发现阶段(相似 paxos 读阶段)、同步阶段、写阶段(相似 paxos 写阶段)

 

在同步阶段以前,ZAB 协议也存在一个和 Paxos 算法中的读阶段很是相似的过程,称为发现(Discovery)阶段。

 

在同步阶段中,新的 Leader 会确保存在过半的 Follower 已经提交了以前 Leader 周期中的全部事务 提议 。

这一同步阶段的引入,可以有效地保证 Leader 在新的周期中提出事务提议以前,全部的进程都已经完成了对以前全部事务提议的提交

一旦完成同步阶段后,那么 ZAB 就会执行和 Paxos 算法相似的写阶段。

 

 总的来说,ZAB 协议和 Paxos 算法的本质区别在于,二者的设计目标不太同样。

ZAB 协议主要用于构建一个高可用的分布式数据主备系统,例如ZooKeeper,而 Paxos 算法则是用于构建一个分布式的一致性状态机系统。

 

五 Zookeeper 应用

 

ZooKeeper 目录有几个特色,有临时目录,永久目录,顺序目录,强一致性(顺序访问)和 watcher 机制。

利用这些特色,咱们能够实现:

  • 发布订阅,例如一些配置信息;

     

  • 负载均衡,例如kafka生产,消费均衡;

     

  • master选举,例如 hbase 利用它 hmaster 选举;

     

  • 主备切换,例如 hdfs 的 HA 利用它进行切换。

     

  1. 发布订阅

 

例如:咱们的数据库配置信息文件就能够放到 ZooKeeper 上。 
利用 ZooKeeper 的 watcher 机制实现配置变动,程序在运行中就能够获取到最新的配置信息,不须要起停。

 

2. ZooKeeper HA 应用(主备切换)

 

hdfs 的 HA,它的主备切换用的是 ZooKeeper 来作 Active standby 之间切换的。

大体步骤:

    1. 多个 nodemanager 同时向 ZooKeeper 注册一个数据节点 lock 。由于 ZooKeeper 是强一致性的,因此只能有一个注册成功,注册成功的那个就是 active 

    2. 没有注册成功的否成了 standby,而后在 lock 目录上注册监听事件 watcher。 

注意:注册的 lock 节点目录是临时节点,若是 active 挂了,这个目录也就没了,而且这个 lock 目录是有权限控制的 ACL,防止 active 假死后从新链接出现脑裂。

 

  1. 主备切换:当 active 挂掉之后,会话结束,临时目录自动删除。其余 standby 监听到临时目录删除了,各个 standby 从新同时进行建立带权限的临时目录。成功的改成 active,没有成功的仍是standby

     

  2. 若是挂掉的 active 启动后,发现没有权限范围lock临时目录,自动更改为 standby 状态。 

这是 ZooKeeper 主备切换应用,利用临时目录,ACL,watcher机制实现。

 

3. master选举 

 

利用 Zookeeper master 选举其实很简单,和主备切换同样。 


利用强一致性同时建立同一个目录,最后只能一个成功,成功那个节点会返回成功状态,其余节点返回异常,成功的那个就成为 master,其余节点就改为 slave 。

 

4. Zookeeper 在 hbase 中应用

 

hmaster 监控 regionserver 是否挂掉。

首先,rs(regionserver简称)在ZooKeeper注册一个临时目录rs/[hostname] 目录,而后 hmaster 注册 watcher 监控 rs 目录下面变化就能够发现 rs 服务器是否挂掉。

元数据存储(订阅发布):每一个 region 存储信息位置和状态,都放在 ZooKeeper 上存储,以便你们都能订阅目前 region 所处的状态,好比 region 是在合并仍是在切割,有多少个 region 分别在哪一个regionserver 上。

因此客户端访问先访问 Zookeeper 获得位置信息去读取数据,不通过hmaster。

 

5. Zookeeper 在kafka中应用

 

kafka 在 Zookeeper 注册的信息

首先,kafka 会把 broker 建立到 Zookeeper 临时目录上。

/broker/ids/[1-n] 表示 broker 还活着。而后 topic 信息建立到 Zookeeper 临时目录/brokers/topics/[topicname]/paritiong 信息。若是有消费者,消费者也会在 Zookeeper 建立本身消费信息的offset信息等临时目录。

kafka 注册 broker 和 topic 信息使为了生产消费时负载均衡,这就利用到 Zookeeper 负载均衡。消费生产者监控到 broker 和 topic ,topic 和 partition 之间的数量,进行从新排序。

 

参考书籍:

《从Paxos到Zookeeper 分布式一致性原理与实践》

 

 

        少侠,我看你骨骼精奇,关注一下,我这本武林秘籍就是你的了~

 

相关文章
相关标签/搜索