【ZOOKEEPER系列】分布式架构与一致性协议

ZOOKEEPER系列

分布式架构与一致性协议

首先了解分布式架构先要知道什么是分布式系统

根据经典分布式领域的著作《分布式系统概念与设计》一书中指出,分布式系统是:

一个硬件或者软件组件分布在不同的网络计算机上,彼此之间通过消息传递进行通信和协调的系统

严格的将讲,同一个分布式系统中的计算机在空间部署上是可以随意分布的,这些机器可能被放在不同的机柜上,也可能在不同的机房中,甚至分布在不同的城市。无论如何,一个标准的分布式系统在没有任何特定业务逻辑约束的情况下,都会有如下几个特征

  • 分布性

分布式系统中的多台计算机都会在空间上随意分布,同事机器的分布情况也可能会随时变动

  • 对等性

分布式系统中的计算机没有主从之分,没有控制整个系统的主机,也没有被控制的从机,组成分布式系统的所有计算机节点都是对等的

  • 并发性

在一个计算机网络中程序运行过程中的兵法操作是非常常见的行为,在分布式系统的的多个节点,也有可能会并发的操作一些共享的资源,例如数据库和分布式存储

  • 缺乏全局时钟

在上面的描述中,我们讲到,一个分布式系统是不受空间上的约束的,在分布式的系统中很难定义两个时间谁先谁后,就是因为分布式系统缺乏一个全局的时钟序列控制关于分布式的时间的时间的对其在Leslie Lamport中的论文中已经做了很深刻的讲解

  • 故障中会发生

组成分布式系统的所有计算机,都有可能会发生任何形式的故障,一个被大量工程时间所校验过的黄金真理是: 任何在设计阶段考虑到的异常情况,一定会在系统实际运行中发生,所以,在系统的设计时不能放过任何异常情况

分布式环境的各种问题

分布式系统体系结构从其出现之初就面临着许多问题和挑战,此处简单讲几个典型问题

  • 通信异常

从集中式向分布式的演变过程中,必然会有网络的因素,由于网络本身是不可靠的,因此带来了一些额外的问题,两个节点之间需要网络通信,网络光纤、路由器或者DNS等设备或者系统不可用都会伴随着网络不可能的风险,有时即使两个节点能正常通信但是延迟非常高的情况下,会可能导致消息收发过程中的消息丢失和消息延迟

  • 网络分区

当网络由于发生异常情况,导致分布式系统中的部分及节点之间的网络延迟不断增大,只有部分节点之间能正常通信,由于一些选举算法会导致有两个节点集群可以执行传来的指令时,我们将这个现象称为网络分区也就是俗称的“脑裂”,这些局部小集群有些够独立完成原本需要整个分布式系统才能完成的功能,这就对分布式的一致性提出了很大的挑战

  • 三态

在单机的状态下,我们所有的事务或者指令,只有两种,要么成功,要么失败,但是在分布式的集群当中,我们有三种状态,成功、失败、和超时。因为当网络出现问题的时候,就有可能会出现超时的现象
通常有下面两种情况:

  1. 由于网络问题,请求消息没有能够成功的发送给接收方,那么这个消息就是在给接收方的时候丢失了
  2. 请求消息传给接收方后,接收方进行了处理操作,在返回给请求方时,出现了消息丢失

    • 节点故障

节点故障是分布式环境下另一个比较常见的问题,指的是组成分布式系统中的每个节点都有可能出现宕机的现象,并且每天都在发生

从ACID 到CAP/BASE

  • ACID

事务是由一些列对系统数据进行访问或者更新操作组成的一个程序执行单元,狭义的事务指的是数据库事务,这里我们不作为重点来讲,我们还是主要来讲解分布式事务

A(Atomiciry)原子性

C(Consistency)一致性

I(Isolation)隔离性

D(Durability)持久性

  • CAP和BASE理论

CAP理论告诉我们 一个分布式系统不可能同时满足一致性可用性和分区容错性这三个基本需求,最多同时满足这三个当中的两项
(一般我们都是在一致性和分区容错性之间寻找平衡)

BASE理论是BasicallyAvaliable(基本可用) Soft state(软状态)和Eventually consistent(最终一致性) 三个短语的简写,由eBay的架构师提出

基本可用

指的是在分布式系统中出现不可预知故障的时候,允许损失部分可用性,但是绝对不是系统不可用

举个栗子

  1. 响应时间上的损失
    正常情况下,一个在线的搜索引擎需要在0.5s之内给用户响应的查询结果,由于系统故障可能响应时间增加到1-2s

  2. 功能上的损失
    正常情况下一个购物网站在大促销的时候由于用户的购物行为激增,为了保护购物系统的稳定性,部分消费者可能会被引导到一个降级的界面

软状态

和硬状态相对应,是指允许系统中的数据存在中间状态,并认为这个中间状态的存在不会影响系统整体的可用性,即:允许系统在不同节点的数据副本之间进行数据同步的过程存在延迟

最终一致性

这个问题非常重要,最终一致性强调的是在系统中的所有数据副本,在经过一段时间的同步后,最终能够达到一个一直的状态,因此,最终一致性的本质是需要系统保证最终的数据能够达到一致,而不要求实时保证系统数据的一致性

在实际的工程中,一般主要有一下五个主要变种

  1. 因果一致性 如果进程A在更新完某个数据项后通知了B那么进程B之后对该数据访问都应该能获取到进程A更新后的最新之,并且如果进程B要对数据项进行操作的话,务必要基于进程A更新后的最新值,不能发生更新丢失的现象,与此同时,与进程A无因果关系的进程C的数据访问则没有这样的限制

  2. 读己一致性 进程A更新了一个数据项之后,它总是能够自己访问到更新过的最新值,而不会看到旧值,也就是说对于单个数据获取者来说,其多到补数据一定不会比自己上次写入的值旧,可以看做一种特殊的因果一致性

  3. 会话一致性 再一个会话当中,系统能保证在同一个有效地会话中能够有效地实现“读己一致性”,也就是说,执行更新操作之后,客户端能够在同一个会话中始终读取到该数据项的最新值
  4. 单调读一致性 一个进程从系统中读取出一个数据项的某个值后,那么系统对于该进程后续的任何数据访问都不应该返回更旧的值
  5. 单调写一致性一个系统需要能够保证来自同一个进程的写操作被有顺序的执行。

分布式架构的问题我们就讲的差不多了,接下来我们要讲一些如何能保证系统的一致性,也就是一致性协议。

一致性协议

说到一致性协议就需要讲到2PC和3PC

  • 2PC

也就是Two-Phase-Commit(二阶段提交)
将事务的提交过程分为两个阶段来进行处理,过程如下

  1. 提交事务请求

    1.1事务询问

    协调者向所有参与者发送事务内容,询问是否可以执行事务的提交操作,并等待所有参与者的相应

    1.2 执行事务

    各参与者节点执行事务操作,将Undo和Redo信息记录到日志中

    1.3 各参与者向协调者反馈事务询问的响应

    如果参与者成功执行了事务操作,就返回给协调者Yes响应,相反没有成功执行事务,返回No表示事务不能执行

  2. 执行事务提交

在二阶段中,协调者会根据参与者的反馈情况来最终决定是否可以进行事务的提交,包含两种可能性

2.1.执行事务提交

    2.1.1 发送提交请求

协调者向所有参与者发出Commit请求
    2.1.2事务提交

参与者收到Commit请求后会正式执行事务的提交错做,并在完成提交事务之后释放整个事务执行期间的占用的事务资源

    2.1.3 反馈事务提交结果

参与者完成事务提交之后,向协调者发送Ack消息

    2.1.4完成事务

协调者接收所有参与者反馈的Ack消息后完成事务

2.2中断事务

    任何一个参与者向协调者反馈了No的相应,或者在等待超时之前,协调者无法接收到所有参与者的反馈响应,那么就会中断事务

    2.2.1发送回滚请求

    协调者向所有参与者节点发出Rollback请求

    2.2.2事务回滚

    参与者接收到Rollback请求后,会利用其在阶段一中记录的Undo信息来执行事务的回滚操作,并在完成回滚之后释放整个事务执行期间占用的资源

    2.2.3反馈事务回滚结果

    参与者在完成事务回滚之后,向协调者发送Ack消息

    2.2.4中断事务

    协调者接收到所有参与者的反馈的Ack消息后,完成事务中断

大概的样子就是我们描述的这样,我们能比较明显的看到优缺点

优点:原理简单,实现起来比较方便

缺点:同步阻塞、单点问题、脑裂、多次RPC调用占用资源

同步阻塞:再一次请求过程中,必须要所有参与者回复才能继续进行,如果有一台机器不回复,就会导致系统无法进行任何操作

单点问题:我们可以看出,这个系统里面,协调者是最重要的一个组成部分,如果协调者崩溃,会直接导致整个系统不可用

多次RPC调用:事务执行之前要请求通信,执行完事务之后要通信,提交事务执行之前要通信,执行一次事务提交需要多次RPC调用才能完成,浪费系统资源

  • 3PC

是Three-Phase-Commit的缩写,也就是三阶段提交,是2PC的改进版,将2PC中的提交事务请求阶段细化成了两个阶段,CanCommit,PreCommit,和do Commit三个阶段

  1. 阶段一CanCommit

    1.1 事务询问

    协调者想所有的参与者发送一个包含事务内容的canCommit请求,询问是否可以进行执行事务的提交操作,并开始等待参与者的响应

    1.2 各个参与者向协调者反馈事务询问的响应

    参与者接收到各自协调者的反馈后,正常情况下,如果可以正常执行事务就返回Yes,否则返回No

2.阶段二PreCommit

有两个可能,能提交和不能提交,能提交就提交,不能提交就回滚

2.1 执行事务的预提交 

2.1.1发送预提交请求

协调者向所有参与者节点发出preCommit的请求,并进入Prepared阶段

2.1.2事务预提交

参与者接收到preCommit的请求后,会执行事务的操作,并将Undo和Redo记录到事务日志中

2.1.3各个参与者向协调者反馈事务执行情况

如果参与者成功执行了事务操作,那么就会反馈给协调者Ack响应,同事等待最终的指令 提交或者终止

2.2中断事务

2.2.1发送中断请求

协调者向所有节点发出abort请求

2.2.2中断事务

收到abort请求或者等待协调者过程中出现超时,参与者都会中断事务
  1. doCommit

    真正的事务提交,也有可能存在两种情况

    3.1执行提交

    3.1.1发送提交请求

    进入这一阶段,假设所有协调者处于正常工作状态,并且它接收到来自所有参与者的Ack回应,它将从预提交改为提交状态,向所有的参与者发送doCommit请求

    3.1.2事务提交

    参与者收到doCommit请求后,会正式执行事务的提交操作,释放事务的占用资源

    3.1.3反馈事务提交结果

    参与者完成事务提交之后,向协调者发送Ack消息

    3.1.4完成事务

    协调者接收到所有参与者回馈的Ack消息后,完成事务

    3.2中断事务

    3.2.1发送中断请求

    协调者向所有参与者节点发送abort请求

    3.2.2事务回滚

    参与者接收到abort请求后,会利用二阶段做的Undo信息来执行回滚操作,释放资源

    3.2.3返回事务回滚结果

    参与者在完成事务回滚之后,向协调者发送ACK消息

    3.2.3中断事务

    协调者就收到所有参与者反馈的Ack消息后,中断事务

优缺点也是显而易见的

优点:降低了参与者的阻塞范围,能够在单点故障以后继续达成一致

缺点:在参与者接收到preCommit消息后如果出现了网络分区,此时协调者所在的节点也无法进行正常的网络通信,这种情况下,该参与者依然会进行事务的提交,会出现数据的不一致性

Paxos算法和ZAB算法下次再讲

猜你喜欢

转载自blog.csdn.net/qq_34370153/article/details/80956311