您当前的位置:首页 > 电脑百科 > 程序开发 > 架构

分布式系统原理

时间:2020-05-25 11:02:46  来源:  作者:

高可用是指系统无中断的执行功能的能力,代表了系统的可用程度,是进行系统设计时必须要遵守的准则之一。 而高可用的实现方案,无外乎就是冗余,就存储的高可用而言,问题不在于如何进行数据备份,而在于如何规避数据不一致对业务造成的影响。 对于分布式系统而言,要保证分布式系统中的数据一致性就需要一种方案,可以保证数据在子系统中始终保持一致,避免业务出现问题。 这种实现方案就叫做分布式事务,要么一起成功,要么一起失败,必须是一个整体性的事务。

1、理论基础

1.1 CAP

CAP,Consistency Availability Partition tolerance 的简写:

Consistency:一致性,对某个客户端来说,读操作能够返回最新的写操作结果。 Availability:可用性,非故障节点在合理的时间内返回合理的响应。 Partition tolerance:分区容错性,分布式系统中系统肯定部署在多台机器上,无法保证网络做到 100% 的可靠,所以网络分区一定存在,即 P 一定存在。

在出现网络分区后,就出现了可用性和一致性的问题,我们必须要在这两者之间进行取舍,因此就有了两种架构

  • CP 架构
  • AP 架构

1.2 BASE理论

BASE 理论指的是基本可用 Basically Available,软状态 Soft State,最终一致性 Eventual Consistency,核心思想是即便无法做到强一致性,但应该采用适合的方式保证最终一致性。

BASE,Basically Available Soft State Eventual Consistency 的简写: BA:Basically Available 基本可用,分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。 S:Soft State 软状态,允许系统存在中间状态,而该中间状态不会影响系统整体可用性。 E:Consistency 最终一致性,系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。

BASE 理论本质上是对 CAP 理论的延伸,是对 CAP 中 AP 方案的一个补充。

2、分布式事务协议

2.1 二阶段提交协议:2PC

2.1.1 概述

二阶段提交(Two-phase Commit),是指,为了使基于分布式系统架构下的所有节点在进行事务提交时保持一致性而设计的一种算法(Algorithm)。通常,二阶段提交也被称为是一种协议(Protocol)。

在分布式系统中,每个节点虽然可以知晓自己的操作是成功或者失败,却无法知道其他节点的操作是成功或失败。

当一个事务跨越多个节点时,为了保持事务的 ACID 特性,需要引入一个作为协调者的组件来统一掌控所有节点(称作参与者)的操作结果并最终指示这些节点是否要把操作结果进行真正的提交(比如将更新后的数据写入磁盘等等)。

因此,二阶段提交的算法思路可以概括为:参与者将操作成败通知协调者,再由协调者根据所有参与者的反馈情报决定各参与者是否要提交操作还是中止操作。

2.1.2 二阶段提交过程
  • 投票阶段
分布式系统原理

 

image.png

投票阶段执行流程:

  1. 协调者向所有参与者询问是否可以执行提交操作,并开始等待各参与者的响应。
  2. 参与者执行事务操作,如果执行成功就返回 Yes 响应,如果执行失败就返回 No 响应。
  3. 如果协调者接受参与者响应超时,也会认为执行事务操作失败。
  • 提交阶段
分布式系统原理

 

image.png

提交阶段执行流程:

  1. 如果第一阶段汇总所有参与者都返回 Yes 响应,协调者向所有参与者发出提交请求,所有参与者提交事务。
  2. 如果第一阶段中有一个或者多个参与者返回 No 响应,协调者向所有参与者发出回滚请求,所有参与者进行回滚操作。
2.1.3 优缺点
  • 优点 尽量保证了数据的强一致,但不是 100% 一致
  • 缺点 单点故障,由于协调者的重要性,一旦协调者发生故障,参与者会一直阻塞,尤其是在第二阶段,协调者发生故障,那么所有的参与者都处于锁定事务资源的状态中,而无法继续完成事务操作。 同步阻塞,由于所有节点在执行操作时都是同步阻塞的,当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。 数据不一致,在第二阶段中,当协调者向参与者发送提交事务请求之后,发生了局部网络异常或者在发送提交事务请求过程中协调者发生了故障,这会导致只有一部分参与者接收到了提交事务请求。
    而在这部分参与者接到提交事务请求之后就会执行提交事务操作。但是其他部分未接收到提交事务请求的参与者则无法提交事务。从而导致分布式系统中的数据不一致。

2.2 三阶段提交协议:3PC

2.2.1 概述

三阶段提交(Three-phase commit),是为解决两阶段提交协议的缺点而设计的。与两阶段提交不同的是,三阶段提交是“非阻塞”协议。

三阶段提交在两阶段提交的第一阶段与第二阶段之间插入了一个准备阶段,使得原先在两阶段提交中,参与者在投票之后,由于协调者发生崩溃或错误,而导致参与者处于无法知晓是否提交或者中止的“不确定状态”所产生的可能相当长的延时的问题得以解决。

2.2.2 三阶段提交过程
分布式系统原理

 

image.png

询问阶段:CanCommit 协调者向参与者发送 Commit 请求,参与者如果可以提交就返回 Yes 响应,否则返回 No 响应。

准备阶段:PreCommit 协调者根据参与者在询问阶段的响应判断是否执行事务还是终端事务: 如果所有参与者都返回 Yes,则执行事务。 如果参与者有一个或多个参与者返回 No 或者超时,则中断事务。 参与者执行完操作之后返回 ACK 响应,同时开始等待最终指令

提交阶段:DoCommit 协调者根据参与者在准备阶段的响应判断是否执行事务还是中断事务: 如果所有参与者都返回正确的 ACK 响应,则提交事务。 如果参与者有一个或多个参与者收到错误的 ACK 响应或者超时,则中断事务。 如果参与者无法及时接收到来自协调者的提交或者中断事务请求时,会在等待超时之后,会继续进行事务提交。 协调者收到所有参与者的 ACK 响应,完成事务。

2.2.3 解决二阶段提交时的问题:

三阶段提交解决了二阶段提交中存在的由于协调者和参与者同时挂掉可能导致的数据一致性问题和单点故障问题,并减少阻塞。 因为一旦参与者无法及时收到来自协调者的信息之后,他会默认执行提交事务(三阶段),而不会一直持有事务资源并处于阻塞状态(二阶段会)。

2.2.4 三阶段提交的问题:

在提交阶段如果发送的是中断事务请求,但是由于网络问题,导致部分参与者没有接到请求。
那么参与者会在等待超时之后执行提交事务操作,这样这些由于网络问题导致提交事务的参与者的数据就与接受到中断事务请求的参与者存在数据不一致的问题。

所以无论是 2PC 还是 3PC 都不能保证分布式系统中的数据 100% 一致。

2.3 ZAB——zookeeper 原子广播协议

2.3.1 概述

ZAB 协议全称是Zookeeper Atomic Broadcast,是为分布式协调服务 Zookeeper 专门设计的一种支持 崩溃恢复 和 原子广播 协议。 ZAB 协议满足CP,在选举过程中,是不能对外提供服务的。

2.3.3 消息广播

ZAB 协议的消息广播过程(即数据同步过程)使用的是一个原子广播协议,类似一个 二阶段提交过程。对于客户端发送的写请求,全部由 Leader 接收,Leader 将请求封装成一个事务 Proposal,将其发送给所有 Follwer ,然后,根据所有 Follwer 的反馈,如果超过半数成功响应,则执行 commit 操作(先提交自己,再发送 commit 给所有 Follwer)。

广播流程

分布式系统原理

 

image.png

  • 客户端发起一个写操作请求。
  • Leader 服务器将客户端的请求转化为事务 Proposal 提案,同时为每个 Proposal 分配一个全局的ID,即zxid。然后将需要广播的Proposal 依次放到队列中,并且根据 FIFO 策略进行消息发送。
  • Follower 接收到 Proposal 后,会首先将其以事务日志的方式写入本地磁盘中,写入成功后向 Leader 反馈一个 Ack 响应消息。
  • Leader 接收到超过半数以上 Follower 的 Ack 响应消息后,即认为消息发送成功,可以发送 commit 消息。
  • Leader 向所有 Follower 广播 commit 消息,同时自身也会完成事务提交。Follower 接收到 commit 消息后,会将上一条事务提交。

注意: 1、 Leader 服务器与每一个 Follower 服务器之间都维护了一个单独的 FIFO 消息队列进行收发消息,使用队列消息可以做到异步解耦。 Leader 和 Follower 之间只需要往队列中发消息即可 2、Leader 在收到客户端请求之后,会将这个请求封装成一个事务,并给这个事务分配一个全局递增的唯一 ID,称为事务ID(ZXID),ZAB 协议需要保证事务的顺序,因此必须将每一个事务按照 ZXID 进行先后排序然后处理 3、可以认为这是一种简化版本的 2PC,2PC的单点问题(Leader崩溃)这里也会遇到,ZAB是通过崩溃恢复来解决的

2.3.3 崩溃恢复

所谓崩溃恢复,是指当leader崩溃(单点故障)后,重新选举leader并且数据保持一致性(数据同步)。

  • leader选举:
    选举是通过投票来的,主要分为以下几个阶段,
  1. 发起投票:首轮投票,每个节点发出一个投票,先投票给自己,然后再把投票结果广播到集群中别的节点,其他机器。投票内容包含节点的myid(zookeeper安装时要设置的值,表示当前节点id)和zxid(事务id),比如ZK1的投票为(1, 0),ZK2的投票为(2, 0)
  2. 验证投票:每个节点都投票给自己并且广播之后,那么节点就会收到别的节点的投票结果,在收到投票后可以验证投票的有效性,如检查是否是本轮投票、是否来自LOOKING状态的服务器,
  3. 变更投票:验证完收到的投票结果后,处理投票,针对每一个投票,服务器都需要将别人的投票和自己的投票进行比较,规则如下 · 优先检查ZXID。ZXID比较大的服务器优先作为Leader; · 如果ZXID相同,那么就比较myid。myid较大的服务器作为Leader服务器; 根据以上规则变更自己的投票,然后广播第二轮投票,还是同样的过程,先验证投票,然后变更投票,变更完成以后统计票仓(本轮投票过程中接收到的别的节点的投票信息)中,是否有超过半数的相同投票,如果有,则其就是新的leader,选举结束;如果没有,则继续发起投票,知道选出leader。
分布式系统原理

 

image.png

由上面规则可知,通常那台服务器上的数据越新(ZXID会越大),其成为Leader的可能性越大,也就越能够保证数据的恢复。如果ZXID相同,则SID越大机会越大。

  • 数据同步:
    上面的leader选举结束后,只有当新的leader和follower同步数据之后,才能对外提供服务。
    同步分为以下几个阶段:
  1. 所有follower上报自己最后接收的事务的任期epoch(每个Proposal都包含了一个epoch值,用来代表当前的Leader 周期);leader比较所有的任期,选取最大的epoch,加1后作为当前的任期E=E+1,并且将任期epoch广播给所有follower;follower将任期改为leader发过来的值之后,返回给leader当前follewer节点上的事务队列L;
  2. leader从队列集合中选取任期最大的队列,如果有多个队列任期都是最大,则选取事务编号n最大的队列Lmax(通常就是leader节点自己的事务队列,因为选举leader时,就是选出的事务zxid最大的节点),并将其广播给各个follower,follower接收队列替换自己的事务队列,并且执行队列中的事务(执行过跳过,未执行执行),执行完以后反馈给leader 表明自己已经完成同步(追上来了),leader 收到过半反馈后,发送commit 消息;follower 接收到commit 消息后,提交事务; 至此各个节点的数据达成一致,zookeeper恢复正常服务。

注意:在zk选举中,通过投票已经确认leader服务器是最大的zxid的节点了,所以同步过程没有那么复杂。 同步阶段主要是利用 Leader 前一阶段获得的最新 Proposal 历史,同步集群中所有的副本。只有当超过半数的节点都同步完成,准 Leader 才会成为真正的 Leader。Follower 只会处理 zxid 比自己 lastZxid 大的 Proposal。

3、最终一致性分布式事务方案

3.1 本地消息表

本地消息表的核心思想是将分布式事务拆分成本地事务进行处理。

例如,在订单系统新增一条消息表,将新增订单和新增消息放到一个事务里完成,然后通过轮询的方式去查询消息表,将消息推送到 MQ,库存系统去消费 MQ。

分布式系统原理

 

image.png

执行流程:
  1. 订单系统,添加一条订单和一条消息,在一个事务里提交。
  2. 订单系统,使用定时任务轮询查询状态为未同步的消息表,发送到 MQ,如果发送失败,就重试发送。
  3. 库存系统,接收 MQ 消息,修改库存表,需要保证幂等操作。
  4. 如果修改成功,调用 RPC 接口修改订单系统消息表的状态为已完成或者直接删除这条消息。 如果修改失败,可以不做处理,等待重试。

订单系统中的消息有可能由于业务问题会一直重复发送,所以为了避免这种情况可以记录一下发送次数,当达到次数限制之后报警,人工接入处理;库存系统需要保证幂等,避免同一条消息被多次消费造成数据一致。

本地消息表这种方案实现了最终一致性,需要在业务系统里增加消息表,业务逻辑中多一次插入的 DB 操作,所以性能会有损耗,而且最终一致性的间隔主要由定时任务的间隔时间决定。

3.2 MQ 消息事务

消息事务的原理是将两个事务通过消息中间件进行异步解耦。

分布式系统原理

 

image.png

从上面可以看出,消息事务一定要保证业务操作与消息发送的一致性,如果业务操作成功,这条消息也一定投递成功。

消息事务依赖于消息中间件的事务消息,基于消息中间件第二阶段提交实现的,RocketMQ 就支持事务消息。RabbitMQ也支持事务消息

执行流程:
  1. 发送 Prepare 消息到消息中间件。
  2. 发送成功后,执行本地事务。
  3. 如果事务执行成功,则 Commit,消息中间件将消息下发至消费端。
  4. 如果事务执行失败,则回滚,消息中间件将这条 Prepare 消息删除。
  5. 消费端接收到消息进行消费,如果消费失败,则不断重试。

这种方案也是实现了最终一致性,对比本地消息表实现方案,不需要再建消息表,不再依赖本地数据库事务了,所以这种方案更适用于高并发的场景。

3.3 最大努力通知

最大努力通知相比前两种方案实现简单,适用于一些最终一致性要求较低的业务,比如支付通知,短信通知这种业务。 以支付通知为例,业务系统调用支付平台进行支付,支付平台进行支付,进行操作支付之后支付平台会尽量去通知业务系统支付操作是否成功,但是会有一个最大通知次数。 如果超过这个次数后还是通知失败,就不再通知,业务系统自行调用支付平台提供一个查询接口,供业务系统进行查询支付操作是否成功。

分布式系统原理

 

image.png

执行流程:
  1. 业务系统调用支付平台支付接口, 并在本地进行记录,支付状态为支付中。
  2. 支付平台进行支付操作之后,无论成功还是失败,都需要给业务系统一个结果通知。
  3. 如果通知一直失败则根据重试规则进行重试,达到最大通知次数后,不再通知。
  4. 支付平台提供查询订单支付操作结果接口。
  5. 业务系统根据一定业务规则去支付平台查询支付结果。

这种方案也是实现了最终一致性。

3.4 补偿事务 TCC

TCC,Try-Confirm-Cancel 的简称,针对每个操作,都需要有一个其对应的确认和取消操作。 当操作成功时调用确认操作,当操作失败时调用取消操作,类似于二阶段提交,只不过是这里的提交和回滚是针对业务上的,所以基于 TCC 实现的分布式事务也可以看做是对业务的一种补偿机制。

3.4.1 TCC 第三个阶段:
  • Try 阶段:对业务系统做检测及资源预留、冻结。
  • Confirm 阶段:对业务系统做确认提交,Try 阶段执行成功并开始执行 Confirm 阶段时,默认 Confirm 阶段是不会出错的。即:只要 Try 成功,Confirm 一定成功。
  • Cancel 阶段:在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。

在 Try 阶段,是对业务系统进行检查及资源预览,比如订单和存储操作,需要检查库存剩余数量是否够用,并进行预留,预留操作的话就是新建一个可用库存数量字段,Try 阶段操作是对这个可用库存数量进行操作。

3.4.2 TCC执行流程:

步骤一(Try 阶段):订单系统将当前订单状态设置为支付中,库存系统校验当前剩余库存数量是否大于 2,然后将可用库存数量设置为库存剩余数量 -2,并且设置冻结库存为2

  • image.png

步骤二(Confirm 阶段):如果 Try 阶段执行成功,执行 Confirm 阶段,将订单状态修改为支付成功,库存剩余数量修改为可用库存数量。

  • image.png

步骤三(Cancel 阶段):如果 Try 阶段执行失败,执行 Cancel 阶段,将订单状态修改为支付失败,可用库存数量修改为库存剩余数量。

  • image.png
分布式系统原理

 

image.png

3.4.3 基于 TCC 实现的分布式事务框架

ByteTCC,github.com/liuyangming tcc-transaction:github.com/changmingxi



Tags:分布式系统   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
随着移动互联网技术的快速发展,在新业务、新领域、新场景的驱动下,基于传统大型机的服务部署方式,不仅难以适应快速增长的业务需求,而且持续耗费高昂的成本,从而使得各大生产厂商...【详细内容】
2021-12-08  Tags: 分布式系统  点击:(23)  评论:(0)  加入收藏
分布式一致性算法概要随着各种高并发访问、海量数据处理等应用场景越来越多,为了应对这些使用场景,分布式系统应运而生。分布式系统得以发展,得益于诸多优点,比如:可以避免 单点...【详细内容】
2021-04-13  Tags: 分布式系统  点击:(238)  评论:(0)  加入收藏
分布式系统的经典理论分布式系统从诞生到现在已经有几十个年头了,其中伴随着一些很重要的基础理论,正是这些影响深远的基础理论,奠定了分布式系统的坚实基础,造就了分布式领域的...【详细内容】
2021-04-13  Tags: 分布式系统  点击:(263)  评论:(0)  加入收藏
分布式理论知识1、分布式系统架构1.1基础概念分布式 : 将一个单体项目分成很多个模块,各个模块协同工作,各个模块构成了分布式系统集群:针对单个模块或者单个系统在多台服务器上...【详细内容】
2021-01-28  Tags: 分布式系统  点击:(111)  评论:(0)  加入收藏
一致性问题一致性问题是分布式领域最重要、最基础的问题。一致性/Consistency,是说在有多个服务节点的情况下,执行一些列操作,在约定协议的保障下,使得他们对外的处理结果,能达...【详细内容】
2020-12-15  Tags: 分布式系统  点击:(149)  评论:(0)  加入收藏
在分布式系统,尤其是微服务系统中,一次外部请求往往需要内部多个模块,多个中间件,多台机器的相互调用才能完成。在这一系列的调用中,可能有些是串行的,而有些是并行的。在这种情况...【详细内容】
2020-12-11  Tags: 分布式系统  点击:(158)  评论:(0)  加入收藏
现如今可谓是微服务、分布式、IoT(物联网)横行的时代,作为一名开发者始终还是要保持一定的危机意识,特别是在日常的项目开发中,若是有机会接触到一些关于微服务、分布式下的应用...【详细内容】
2020-12-01  Tags: 分布式系统  点击:(114)  评论:(0)  加入收藏
分布式系统如何寻址?通过 RPC 框架,能够解决服务之间的跨网络通信问题,是微服务改造的基础。服务拆分之后,需要维护更多细粒度的服务,这样就涉及到 RPC 客户端服到服务端的 部署...【详细内容】
2020-11-04  Tags: 分布式系统  点击:(103)  评论:(0)  加入收藏
上一篇《CAP》写完之后,我又反复回看了多次,发现最后的一部分表达CAP、ACID、BASE、“BACP(自造)”关系时有一些问题,并且不是很严谨,但是无奈已经发送过的内容,无法支持修改,并且有挺多小伙伴都在私聊我确认细节,这里我来重...【详细内容】
2020-09-16  Tags: 分布式系统  点击:(46)  评论:(0)  加入收藏
介绍OAuth(开放授权)是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方应用或分享他们数据的所有内容。OAuth...【详细内容】
2020-08-18  Tags: 分布式系统  点击:(65)  评论:(0)  加入收藏
▌简易百科推荐
为了构建高并发、高可用的系统架构,压测、容量预估必不可少,在发现系统瓶颈后,需要有针对性地扩容、优化。结合楼主的经验和知识,本文做一个简单的总结,欢迎探讨。1、QPS保障目标...【详细内容】
2021-12-27  大数据架构师    Tags:架构   点击:(5)  评论:(0)  加入收藏
前言 单片机开发中,我们往往首先接触裸机系统,然后到RTOS,那么它们的软件架构是什么?这是我们开发人员必须认真考虑的问题。在实际项目中,首先选择软件架构是非常重要的,接下来我...【详细内容】
2021-12-23  正点原子原子哥    Tags:架构   点击:(7)  评论:(0)  加入收藏
现有数据架构难以支撑现代化应用的实现。 随着云计算产业的快速崛起,带动着各行各业开始自己的基于云的业务创新和信息架构现代化,云计算的可靠性、灵活性、按需计费的高性价...【详细内容】
2021-12-22    CSDN  Tags:数据架构   点击:(10)  评论:(0)  加入收藏
▶ 企业级项目结构封装释义 如果你刚毕业,作为Java新手程序员进入一家企业,拿到代码之后,你有什么感觉呢?如果你没有听过多模块、分布式这类的概念,那么多半会傻眼。为什么一个项...【详细内容】
2021-12-20  蜗牛学苑    Tags:微服务   点击:(9)  评论:(0)  加入收藏
我是一名程序员关注我们吧,我们会多多分享技术和资源。进来的朋友,可以多了解下青锋的产品,已开源多个产品的架构版本。Thymeleaf版(开源)1、采用技术: springboot、layui、Thymel...【详细内容】
2021-12-14  青锋爱编程    Tags:后台架构   点击:(21)  评论:(0)  加入收藏
在了解连接池之前,我们需要对长、短链接建立初步认识。我们都知道,网络通信大部分都是基于TCP/IP协议,数据传输之前,双方通过“三次握手”建立连接,当数据传输完成之后,又通过“四次挥手”释放连接,以下是“三次握手”与“四...【详细内容】
2021-12-14  架构即人生    Tags:连接池   点击:(17)  评论:(0)  加入收藏
随着移动互联网技术的快速发展,在新业务、新领域、新场景的驱动下,基于传统大型机的服务部署方式,不仅难以适应快速增长的业务需求,而且持续耗费高昂的成本,从而使得各大生产厂商...【详细内容】
2021-12-08  架构驿站    Tags:分布式系统   点击:(23)  评论:(0)  加入收藏
本系列为 Netty 学习笔记,本篇介绍总结Java NIO 网络编程。Netty 作为一个异步的、事件驱动的网络应用程序框架,也是基于NIO的客户、服务器端的编程框架。其对 Java NIO 底层...【详细内容】
2021-12-07  大数据架构师    Tags:Netty   点击:(17)  评论:(0)  加入收藏
前面谈过很多关于数字化转型,云原生,微服务方面的文章。虽然自己一直做大集团的SOA集成平台咨询规划和建设项目,但是当前传统企业数字化转型,国产化和自主可控,云原生,微服务是不...【详细内容】
2021-12-06  人月聊IT    Tags:架构   点击:(23)  评论:(0)  加入收藏
微服务看似是完美的解决方案。从理论上来说,微服务提高了开发速度,而且还可以单独扩展应用的某个部分。但实际上,微服务带有一定的隐形成本。我认为,没有亲自动手构建微服务的经历,就无法真正了解其复杂性。...【详细内容】
2021-11-26  GreekDataGuy  CSDN  Tags:单体应用   点击:(35)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条