分布式理论笔记

分布式理论

分布式理论基础

分布式系统定义

分布式系统是一个硬件或软件分布在不同的机器上,彼此之间仅通过消息传递进行通信和协调的系统。

通俗的理解,所谓分布式系统,就是将一个业务拆分成多个子业务,然后部署到不同的服务器节点,组成的一个完整的系统叫做分布式系统。
分布式系统的两个重要因素
  • 组件是分布在网络计算机上
  • 组件之间仅仅通过消息传递来通信并协调行动
分布式系统的优势

每个服务器的算力是有限的,但是通过分布式系统,由N个服务器组成的分布式集群系统,理论上来说算力是无限扩张的。
类比来说,分布式系统就是一群人一期干活,人多力量大。

分布式架构的意义

从单机单用户到单机多用户,再到现在的网络时代,应用系统发生了很多的变化,为什么要用分布式系统呢?

  • 升级单机处理能力的性价比越来越低
  • 单机处理能力存在瓶颈
  • 对于稳定性和可用性的要求

分布式系统所面临的问题

通信异常

分布式系统需要在不同的服务节点间进行通信,必然涉及到网络因素,由于网络本身是不稳定的,因此每次网络通信都伴随着网络不可用的风险,可能是光纤、路由、DNS等硬件设备或系统不可用,这些最终都会导致分布式系统无法顺利完成一次网络通信。

另外,分布式系统各个节点之间的网络通信延迟肯定大于单机系统,这会影响消息的收发过程,因此丢失消息和消息延迟是分布式系统非常普遍的问题。

网络分区

分布式系统由于网络异常,导致各个几点之间的网络延迟不断增大,最终会导致系统中只有部分节点能够进行正常通信,而另外一些节点则不能,这种情况称为网络分区,也称为“脑裂”现象。

当出现网络分区时,各个子系统之间无法通信,但子系统内部网络确实正常的,从而导致整个分布式系统的网络环境被切分成若干个孤立的区域,分布式系统出现局部小集群。极端情况下,可能每个小集群都能完成原本需要整个分布式系统才能完成的功能,包括数据的事务处理,这就引出了分布式一致性问题。

三态

单机系统中,一次请求对应一个明确的响应,要么成功要么失败。

而在分布式系统中,由于网络可能会出现各种各样的问题,因此,每次分布式系统每一次请求和响应存在“三态”概念:成功、失败和超时。

超时通常有两种情况:

  • 由于网络原因,改请求没有被发送到接收方,而是在发送过程中就发生了丢失现象
  • 该请求成功的被接收方接收并进行处理后,但是在返回消息给发送方的过程中,发生了消息丢失
节点故障

组成分布式系统的节点出现宕机或僵死现象叫做节点故障,在分布式系统中,每个几点都有可能出现故障,并且经常发生。因此,节点故障是分布式系统非常常见的问题。

分布式一致性

案例

  • 火车购票

假设你国庆准备坐火车去北京,当你购票时发现余票只剩一张。但是在你购票的同时,其他人可能也要抢这张车票。而购票系统往往是分布式的,假如购票系统没有进行一致性保障,可能最后去北京的这张票会被多个人买到,那就乱套了。。。

因此,在购票系统必须具备严格的一致性,系统中的数据每时每刻必须都是准确无误的。

  • 银行转账

假如你有一张招商银行的卡,有一张工商银行的卡,现在你要通过招商银行转账给工商银行。当你转账时,往往会看到一个提示:“您的转账将会N个工作日内到账”。

对于转账来说,到账的时间可能没那么及时,但是钱最后一定会到账。

  • 网上购物

当你发现一双心仪已久的鞋子会在双11凌晨1点优惠促销时,你会定好闹钟,然后等到时间迅速点击购买按钮,选择收获地址,然后确认订单。然而在你点击下单时,系统却告知:“库存不足!”,然而你清楚地记得刚才点购买时,库存明明不为0。

实际上,点击购买时看到地库存数量并不一定是真实的库存量,只有在下单时,系统才会校验商品的真实库存,判断是否能购买。然而,用户是无感知的,只会觉得是自己手慢了。。。

案例解读

  • 有些系统,既要快速地响应客户,同时还要保证系统的数据对任何一个客户来说都必须是真实可靠的,像12306网站这种。
  • 有些系统,需要为用户保证绝对可靠的数据安全,虽然在数据一致性上存在延迟,但能保证数据严格的一致性,像银行转账系统。
  • 有些系统,虽然向用户展示了一些“错误”的数据,但是用户并不知道。但是在整个系统使用过程中,一定会在某个流程上对系统数据进行校验,像购物系统。

数据一致性

概念

在分布式存储系统中,通常以多副本冗余的方式实现数据的可靠存储。同一份数据的多个副本必须保证一致,而数据的多个副本又存储在不同的节点中,这里的分布式一致性问题就是存储在不同节点中的数据副本(或称为变量)的值必须一致。

多个副本之间往往通过数据复制来实现数据同步,然而数据复制存在延时问题,即:客户端C1将变量K由V1更新为V2,客户端C2无法立即读取到更新后的值V2,需要等待数据同步完成后才能读取到最新的值。这个等待的过程就是延时。

解决延时问题的一种思路就是将写入动作阻塞,直到通过数据复制完成数据同步后,才完成写入动作。但这样会导致写入性能下降,当系统存在大量的写请求,所有写请求都会阻塞,势必导致系统整体性能急剧下降。

总的来说,我们无法找到一种能够满足分布式系统所有系统属性的分布式一致性解决方案。分布式系统需要重点考虑和权衡如何去保证数据一致性,同时又不影响系统运行的性能。

强一致性

这种一致性最符合用户直觉,它要求系统写入什么,读出来的也是什么,用户体验好。但实现起来往往对系统性能影响很大。

弱一致性

约束系统在写入后,不承诺立即可以读到写入的值,也不承诺多久之后数据能够达到一致,但会尽可能地保证到某个时间级别(比如秒级)后,数据能够达到一直状态。

最终一致性

是弱一致性的一个特例,系统会保证在一定时间内,能够达到数据一致的状态。

在弱一致性中非常受推崇的一种一致性模型。

事务一致性

ACID
特性 说明
Atomicity(原子性) 一个事务的所有操作,要么全部完成,要么全部不完成
Consistency(一致性) 指事务开始之前和事务结束之后,数据的完整性约束没有被破坏。
Isolation(隔离性) 数据库能够防止由于多个并发事务交叉执行而导致数据的不一致。
Durability(持久性) 指事务结束后,对数据的修改是永久的,不会回滚到之前的状态。
分布式事务

分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。通常,一个分布式事务中会涉及对多个数据源或业务系统的操作。

一个分布式事务看做是多个分布式的操作序列组成的,通常把这一系列的操作事务称为子事务。因此,分布式事务也可以被定义成一种嵌套型事务,同时也就具有了ACID事务特性。

分布式事务的目的是保障分布式存储中数据一致性,而跨库事务会遇到各种不可控制的问题,如个别节点宕机,像单机事务一样的ACID是无法奢望的。在分布式系统中,可用性和一致性之间的冲突会被放大(保证随时可用,那么数据可能不一致;保证数据一致,系统可能存在短暂的不可用)。因此,分布式系统在可用性和一致性之间无法寻求一种两全其美的解决方案,由此引出了分布式理论CAP和BASE理论。

CAP定理

概念

在分布式系统中,一致性(Consistency)、可用性(Availability)和分区容错性(Partition Tolerance)3 个要素最多只能同时满足2个,不可兼得。其中,分区容忍性又是不可或缺的。

CAP示意图

选项 描述
Consistency 一致性。分布式环境中,数据在多个副本之间能够保证一致的特性(严格的一致性)。在一致性的 需求下,当一个系统在数据一致的状态下进行更新操作后,应该保证数据的状态仍然处在一致的状态。
Availability 可用性。指系统提供的服务必须一直处于可用的状态,每次请求都能获取到非错的响应,但是不保证获取的数据为最新的数据。
Partition Tolerance 分区容错性。系统在遇到任何网络分区故障时,仍然能够对外提供满足一致性和可用性的服务,除非整个网络环境都发生了故障。

为什么只能3选2

假设有一个系统如下:

CAP3选2原理图

系统由A、B两个节点组成,AB之间通过网络通信来协调工作。如果满足CAP,那么应同时具备以下三点:

  • 一致性:A、B两个节点必须保证数据一致,当A更新时需要向B同步更新数据,同时,B更新时也要向A同步更新数据。
  • 可用性:A、B两个节点必须保证都是可用的。
  • 分区容错性:当A、B之间出现网络分区,A和B都可以对外提供完整的服务。

但是,以上三点是无法同时满足的,因为一旦A、B之间出现网络分区,一致性就无法满足。网络断开的情况下,A、B之间根本无法进行数据同步。如果为了强行满足一致性,必须对网络进行修复,而这可能导致服务暂时不可用,又违背了可用性。

因此,CAP定理指出,一致性、可用性、分区容错性同时最多只能满足2个。

组合 分析结果
CA 满足一致性和可用性,放弃分区容错性。说白了,就是一个整体应用,将数据都放在一个分布式节点上。这样做虽然无法保证100%不出错,但可以避免网络分区带来的负面影响。同时,放弃了P的同时意味着放弃了系统的可扩展性。
CP 满足一致性和分区容错性。一旦遇到网络分区或其他故障,为了保证一致性,放弃可用性。
AP 满足可用性和分区容错性。当出现网络分区或其它故障,为了保障可用性,必须让节点继续对外提供服务,这就意味着放弃了一致性。但并不意味着完全不需要一致性,如果完全放弃一致性,分布式系统的数据就没有意义了。这里的“放弃”指的是放弃强一致性保证最终一致性,系统虽然无法保证数据实时的一致性,但能保证最终回达到一致的状态。这就引入了时间窗口的概念:具体多久能达到数据一致取决于系统涉及,主要包括数据在不同副本之间的复制时间长短。

在分布式系统中,分区容错性必不可少,因此在分布式系统设计时,往往需要在C、A之间寻求平衡。

BASE定理

概念

BASE 是 Basically Available(基本可用)、Soft State(软状态)和 Eventually Consistent(最终一致性)三个短语的简写。BASE 是对 CAP 中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的结论,是基于CAP定理逐步演化而来的。

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

Basically Available(基本可用)

基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性——但这绝不等价于系统不可用。“基本可用”的典型例子:

  • 响应时间上的损失:正常情况下,一个在线搜索引擎需要 0.5 秒内返回给用户相应的查询结果,但由于出现异常(比如系统部分机房发生断电或断网故障),查询结果的响应时间增加到了 1~2 秒。
  • 功能上的损失:正常情况下,在一个电子商务网站上进行购物,消费者几乎能够顺利地完成每一笔订单。但是在一些节日大促购物高峰的时候,由于消费者的购物行为激增,为了保护购物系统的稳定性,部分消费者可能会被引导到一个降级页面。对这部分消费者来说,其他功能(如搜索、查看商品详情)是正常的,下单也不是不可用,只是会收到失败提示。

Soft State(软状态)

相对于一致性,要求多个节点的数据副本都是一致的,这是一种“硬状态”。

软状态指的是:允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个节点的数据副本之间进行数据同步的过程中存在延迟。

Eventually Consistent(最终一致性)

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

最终一致性存在以下五类主要变种:

  1. 因果一致性(Causal consistency)

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

  2. 读己之所写(Read your writes)

    节点A更新一个数据项之后,它自己总是能够访问到更新过的最新值,而不会看到旧值。也就是说,对于单个数据获取者而言,其读取到的数据一定不会比自己上次写入的值旧。因此,读己之所写也可以看作是一种特殊的因果一致性。

  3. 会话一致性(Session consistency)

    会话一致性将对系统数据的访问过程框定在了一个会话当中:系统能保证在同一个有效的会话中实现“读己之所写”的一致性,也就是说,执行更新操作之后,客户端能够在同一个会话中始终读取到该数据项的最新值。

  4. 单调读一致性(Monotonic read consistency)

    如果一个节点从系统中读取出一个数据项的某个值后,那么系统对于该节点后续的任何数据访问都不应该返回更旧的值。

  5. 单调写一致性(Monotonic write consistency)

    一个系统需要能够保证来自同一个节点的写操作被顺序地执行。

在实际系统实践中,可以将其中的若干个变种互相结合起来,以构建一个具有最终一致性的分布式系统。

总的来说,BASE理论面向的是大型高可用可扩展的分布式系统,和传统事务的ACID特性使相反的,它完全不同于ACID的强一致性模型,而是提出通过牺牲强一致性来获得可用性,并允许数据在一段时间内是不一致的,但最终达到一致状态。

同时,在实际的分布式场景中,不同业务单元和组件对数据一致性的要求是不同的,因此在具体的分布式系统架构设计过程中,ACID特性与BASE理论往往又会结合在一起使用。

一致性协议

在分布式系统进行架构设计的过程中,往往需要我们在系统的可用性和一致性之间进行反复权衡。因此,涌现了很多经典的算法和协议,最著名的几种就是二/三阶段提交协议、Paxox算法等。

2PC(二阶段提交)

2PC概念

2PC,是Two-Phase Commit的缩写,即两阶段提交,顾名思义就是把事务提交的过程分成了两个阶段来进行处理。2PC 是计算机网络,尤其是数据库领域中,为了使基于分布式系统架构下的所有节点在进行事务处理过程中能够保持原子性和一致性而设计的一种算法。

在两阶段提交协议中,系统一般包含两类机器(或节点):一类为协调者(coordinator),通常一个系统中只有一个;另一类为事务参与者(participants,cohorts或workers),一般包含多个,在数据存储系统中可以理解为数据副本的个数。协调者负责调度参与者的行为,并最终决定这些参与者是否要把事务进行提交。

阶段一:提交事务请求

2PC第一阶段

第一阶段主要分为以下几个过程:

  • 事务询问

    协调者向参与者发送事务内容,询问是否可以执行事务提交操作,并开始等待各参与者的响应。

  • 执行事务

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

    Undo 记录事务操作前的数据,用来保证一致性。

    Redo 记录事务操作后的数据,用来保证原子性和持久性。

  • 参与者向协调者反馈事务询问响应

    参与者成功执行了事务操作,就返回给协调者 Yes 响应,表示事务可以执行;

    参与者执行事务操作失败,就返回给协调者 No 响应,表示事务无法执行;

    部分参与者可能由于网络故障无法接收到Prepare请求,也无法返回相应的结果给协调者。

阶段一就是协调者向各参与者发起事务的“投票表决”,因此这一阶段也叫投票阶段(voting phase)。

阶段二:执行事务提交

执行事务条件时会根据第一阶段投票结果来进行相应的处理,主要分为两种:

1、提交事务

2PC第二阶段提交事务

  • 发送提交请求

    协调者向所有参与者发出 commit 请求。

  • 事务提交

    参与者接收到 commit 指令后,会执行事务提交操作,完成事务提交后释放事务执行期间占用的事务资源。

  • 反馈事务提交结果

    反馈 ACK 信息给协调者。

  • 完成事务

    协调者在接收到所有参与者的 ACK 响应后,完成事务。

2、中断事务

2PC中断事务

  • 发送回滚请求

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

  • 事务回滚

    参与者接收到 Rollback 指令后,会根据一阶段执行事务操作记录的 Undo 信息来执行回滚操作,完成回滚后释放事务执行期间占用的事务资源。

  • 反馈事务回滚结果

    反馈 ACK 信息给协调者。

  • 中断事务

    协调者在接收到所有参与者的 ACK 响应后,中断事务。

2PC的核心思想是对每个子事务都采用先尝试后提交的处理方式,从而保证其原子性和一致性,因此 2PC 可以看成一个强一致性的算法。

2PC优缺点

  • 优点

    原理简单,实现方便。

  • 缺点

    • 同步阻塞

      在二阶段提交的执行过程中,所有参与该事务的逻辑都处于阻塞状态,各个参与者在等待其它参与者响应的过程中一直阻塞,无法进行其他操作。这种同步阻塞极大的限制了分布式系统的性能。

    • 单点故障

      协调者是整个二阶段提交的核心,如果协调者在事务提交阶段出现问题,那么整个事务流程将无法运转。更重要的是,其它参与者将会一直处于锁定事务资源的状态,而无法继续完成事务操作。

    • 数据不一致

      当协调者向参与者发送commit指令后发生了局部网络异常,或是协调者在尚未发送完所有commit指令就崩溃,导致最终只有部分参与者接收到了commit指令,这将导致严重的数据不一致。

    • 过于保守

      在二阶段投票阶段中,参与者出现故障而导致协调者始终无法获取所有参与者的投票结果,此时协调者只能依靠自身的超时机制来决定是否需要中断事务。这种策略偏向于保守,二阶段提交没有设计较为完善的容错机制,任意一个参与者的失败都会导致整个事务的失败。

3PC(三阶段提交)

3PC概念

3PC,全称 Three Phase Commit,是2PC的改进版。为了弥补2PC的缺点,将2PC提交事务请求(投票阶段)过程一分为二,共形成了由 canCommit、preCommit、doCommit 三个阶段组成的事务处理协议。

3PC协议

阶段一:canCommit

  • 事务询问

    协调者向所有参与者发送包含事务内容的 canCommit 指令,询问是否可以进行事务提交操作,并开始等待所有参与者的响应。

  • 参与者向协调者反馈事务询问响应

    参与者接收到 canCommit 指令,如果认为可以顺利执行事务,则返回 Yes 并进入预备状态,否则返回 No。

阶段二:preCommit

协调者根据 canCommit 阶段获取到的参与者响应结果会有2种执行操作情况:执行事务预提交(所有参与者返回Yes)或者中断事务(存在参与者返回No或是响应超时)。

事务预提交:这里只执行事务操作,并不会真正提交事务,真正提交事务在 doCommit 阶段由协调者决定。

  • 发送预提交请求

    协调者向所有参与者发送 preCommit 指令,进入 prepared 阶段。

  • 事务预提交

    参与者接收到 preCommit 指令,执行事务操作,记录 Undo 和 Redo 信息。

  • 参与者向协调者反馈事务执行结果

    若参与者成功执行了事务操作,那么返回 ACK 信息,同时等待最终指令:Commit 或者 Rollback。

中断事务:只会中断当前参与者事务,整体事务中断在 doCommit 阶段由协调者完成。

  • 发送中断请求

    协调者向所有参与者发送 abort指令。

  • 中断事务

    参与者不管是接收到 abort 指令还是等待协调者指令超时,都会中断事务。

阶段三:doCommit

该阶段做真正的事务提交或者完成事务回滚,根据 preCommit 阶段的不同执行情况也会存在两种情况:

  • 提交事务

    • 发送提交指令

      协调者接收到所有参与者的 ACK 响应,那么会有 prepared 阶段变为提交状态,并向所有参与者发送 doCommit 指令。

    • 事务提交

      参与者接收到 doCommit 指令,正式提交事务,然后释放事务资源。

    • 反馈事务提交结果

      完成事务提交后,向协调者发送 ACK 响应。

    • 完成事务

      协调者接收所有参与者反馈的 ACK 响应后,完成事务。

  • 中断事务

    • 发送中断指令

      协调者向所有参与者发送 abort 指令。

    • 事务回滚

      参与者接收到 abort 指令,根据 Undo 信息进行回滚,然后释放事务资源。

    • 反馈事务回滚结果

      完成事务回滚后,向协调者发送 ACK 响应。

    • 中断事务

      协调者接收所有参与者反馈的 ACK 响应后,中断事务。

3PC的优缺点

  • 优点

    • 3PC是2PC的改进版,最大的优点是降低了参与者的阻塞范围(canCommit 阶段并不阻塞),而2PC在第一阶段(canCommit + preCommit)一直阻塞。
    • 3PC在协调者发生单点故障后继续达成一致,会根据协调者状态进行回滚或者提交事务。
  • 缺点

    脑裂问题依然存在,即在参与者收到 PreCommit 指令后等待最终指令,如果此时协调者无法与参与者正常通信,会导致参与者继续提交事务,造成数据不一致。

2PC和3PC对比

  • 3PC对于协调者和参与者都设置了超时机制,2PC只有协调者有超时机制;
  • 在2PC的准备(投票)阶段和提交阶段之间,插入预提交阶段 preCommit,preCommit 是一个缓冲,保证了在最后提交阶段之前各个参与者节点的状态是一致的。
原创文章 1 获赞 0 访问量 91

猜你喜欢

转载自blog.csdn.net/weixin_43186116/article/details/106179315