分布式系统原理

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

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 二阶段提交过程

  • 投票阶段

投票阶段执行流程:

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

提交阶段执行流程:

  1. 如果第一阶段汇总所有参与者都返回 Yes 响应,协调者向所有参与者发出提交请求,所有参与者提交事务。
  2. 如果第一阶段中有一个或者多个参与者返回 No 响应,协调者向所有参与者发出回滚请求,所有参与者进行回滚操作。

2.1.3 优缺点

  • 优点
    尽量保证了数据的强一致,但不是 100% 一致

  • 缺点

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

2.2 三阶段提交协议:3PC

2.2.1 概述

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

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

2.2.2 三阶段提交过程

询问阶段: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)。

广播流程

  1. 客户端发起一个写操作请求。
  2. Leader 服务器将客户端的请求转化为事务 Proposal 提案,同时为每个 Proposal 分配一个全局的ID,即zxid。然后将需要广播的Proposal 依次放到队列中,并且根据 FIFO 策略进行消息发送。
  3. Follower 接收到 Proposal 后,会首先将其以事务日志的方式写入本地磁盘中,写入成功后向 Leader 反馈一个 Ack 响应消息。
  4. Leader 接收到超过半数以上 Follower 的 Ack 响应消息后,即认为消息发送成功,可以发送 commit 消息。
  5. 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. 变更状态:Leader挂后,余下的Flower服务器都会将自己的服务器状态变更为LOOKING,然后再开始进入Leader选举过程;

  2. 发起投票:首轮投票,每个节点发出一个投票,先投票给自己,然后再把投票结果广播到集群中别的节点,其他机器。投票内容包含节点的myid(zookeeper安装时要设置的值,表示当前节点id)和zxid(事务id),比如ZK1的投票为(1, 0),ZK2的投票为(2, 0)

  3. 验证投票:每个节点都投票给自己并且广播之后,那么节点就会收到别的节点的投票结果,在收到投票后可以验证投票的有效性,如检查是否是本轮投票、是否来自LOOKING状态的服务器,

  4. 变更投票:验证完收到的投票结果后,处理投票,针对每一个投票,服务器都需要将别人的投票和自己的投票进行比较,规则如下
    · 优先检查ZXID。ZXID比较大的服务器优先作为Leader;
    · 如果ZXID相同,那么就比较myid。myid较大的服务器作为Leader服务器;

  5. 统计投票:根据以上规则变更自己的投票,然后广播第二轮投票,还是同样的过程,先验证投票,然后变更投票,变更完成以后统计票仓(本轮投票过程中接收到的别的节点的投票信息)中,是否有超过半数的相同投票,如果有,则其就是新的leader,选举结束;如果没有,则继续发起投票,知道选出leader。

  6. **改变服务器状态 **:选出leader后,变更各服务器状态,leader从LOOKING变成Leader,别的机器变成Flower,然后同步leader数据。

由上面规则可知,通常那台服务器上的数据越新(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。

执行流程:

  1. 订单系统,添加一条订单和一条消息,在一个事务里提交。

  2. 订单系统,使用定时任务轮询查询状态为未同步的消息表,发送到 MQ,如果发送失败,就重试发送。

  3. 库存系统,接收 MQ 消息,修改库存表,需要保证幂等操作。

  4. 如果修改成功,调用 RPC 接口修改订单系统消息表的状态为已完成或者直接删除这条消息。
    如果修改失败,可以不做处理,等待重试。

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

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

3.2 MQ 消息事务

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

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

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

执行流程:

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

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

3.3 最大努力通知

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

执行流程:

  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

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/21417.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Lychee图床】本地电脑搭建私人图床,公网远程访问

文章目录 1.前言2. Lychee网站搭建2.1. Lychee下载和安装2.2 Lychee网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 转发自CSDN风浪越大%鱼越贵的文章:Lychee图床 - 本地配置属于自己的相册管理系统并远…

国潮还能怎么玩?小红书用户画像速看!

所谓“国潮”,概括来说就是“国风潮流”。主要有两层含义:其一,有中国文化和传统的基因;其二,能将传统文化与时下潮流相融合,使产品更具时尚感。在“国潮”元年之前,“国潮”大多指狭义上的特定…

【开发者指南】如何在MyEclipse中编辑HTML或JSP文件?(一)

MyEclipse v2022.1.0正式版下载 如果您有HTML或JSP文件要编辑,这里将介绍如何编辑。查找以下信息: 编辑源代码大纲和属性视图参数页面 该功能在MyEclipse中是可用的。 一、HTML / JSP编辑器 要编辑HTML或JSP文件,请执行以下操作当中的一…

Git笔记

目录 Git概念 git配置 git的安装 远程仓库配置 忽略跟踪文件 git指令 文件跟踪指令: 查看提交历史 撤消操作 远程仓库的使用 标签 分支 常见错误提示及解决方法 git patch的运用 git中branch/commit/add之间关系 Windows下Git的使用 Git概念 Git 是…

接口优化技巧汇总

1.批处理 批量思想:批量操作数据库,这个很好理解,我们在循环插入场景的接口中,可以在批处理执行完成后一次性插入或更新数据库,避免多次IO。 //批量入库 batchInsert();2.异步处理 异步思想:针对耗时比较…

Nacos-04-@RefreshScope自动刷新原理

Nacos动态刷新原理 Nacos做配置中心的时候,配置数据的交互模式是有服务端push推送的,还是客户端pull拉取的? 短轮询 不管服务端的配置是否发生变化,不停发起请求去获取配置,比如支付订单场景中前端JS不断轮询订单支…

mathtype公式符号显示不对

文章目录 问题解决方法结果 记录攥写论文遇到的问题及解决方法 问题 使用mathtype编辑公式过后,发现公式显示不对,出现两种问题: 1:部分符号变为方框 2:符号大小异常 例如: 解决方法 第一种&#xff1a…

【Linux 之五】 Linux中使用fdisk命令实现磁盘分区

最近由于工作的需要,初步研究了uboot中的fastboot实现方式。研究fastboot不可避免的需要了解磁盘分区的相关知识点,在linux下可以使用fdisk命令实现磁盘的分区。好了,下面步入正题。 1. 查看帮助信息(fdisk --help) …

我们详细讲讲UI自动化测试最佳设计模式POM

概念 什么是POM? POM是PageObjectModule(页面对象模式)的缩写,其目的是为了Web UI测试创建对象库。 在这种模式下,应用涉及的每一个页面应该定义为一个单独的类,类中应该包含此页面上的页面元素对象和处…

skywalking安全认证问题

skywalking安全认证 一、问题二、步骤2.1 skywalking-aop配置文件修改2.2 agent配置文件修改 一、问题 在springboot项目使用java-agent接入skywalking时,为保证两者之间的数据安全传输,准备加个安全认证 参考文章: https://www.helloworld…

亚马逊云科技使用Inf2实例运行GPT-J-6B模型

在2019年的亚马逊云科技re:Invent上,亚马逊云科技发布了Inferentia芯片和Inf1实例这两个基础设施。Inferentia是一种高性能机器学习推理芯片,由亚马逊云科技定制设计,其目的是提供具有成本效益的大规模低延迟预测。时隔四年,2023年…

java版企业电子招投标系统源码 招采系统源码 spring boot+mybatis+前后端分离实现电子招投标系统

spring bootmybatis前后端分离实现电子招投标系统 电子招投标系统解决方案 招标面向的对象为供应商库中所有符合招标要求的供应商,当库中的供应商有一定积累的时候,会节省大量引入新供应商的时间。系统自动从供应商库中筛选符合招标要求的供应商&#x…

【Mybatis】SpringBoot整合Mybatis

唠嗑部分 之前我们说了Mybatis的一些文章,相关文章: 【Mybatis】简单入门及工具类封装-一 【Mybatis】如何实现ORM映射-二 【Mybatis】Mybatis的动态SQL、缓存机制-三 【Mybatis】Mybatis处理一对多、多对多关系映射-四 这篇文章我们来说说SpringBoot如…

SpringCloud学习-实用篇03

以下内容的代码可见:SpringCloud_learn/day03 1.初识Docker 什么是Docker? 项目部署问题:大型项目组件较多,运行环境也较为复杂,部署时会碰到一些问题 依赖关系复杂,容易出现兼容性问题开发、测试、生产环境有差异 Do…

ADS - lesson 1. Patch antenna

Patch antenna 1. 开启 layout command line editor2. layout command line editor应用3. 画馈线4. 插入端口5. EM 冲冲冲6. 结果 1. 开启 layout command line editor ADS主界面 - Tools - App Manager… - 勾选 “layout command line editor” 然后重启软件 2. layout co…

一步一步详解LSTM网络【从RNN到LSTM到GRU等,直至attention】

一步一步详解LSTM网络【从RNN到LSTM到GRU等,直至attention】 0、前言1、Recurrent Neural Networks循环神经网络2、The Problem of Long-Term Dependencies长期依赖的问题3、LSTM Networks4、The Core Idea Behind LSTMs5、Step-by-Step LSTM Walk Through6、Varian…

微信小程序原生开发功能合集十五:个人主页功能实现

本章个人主页功能实现,展示当前登录用户信息、个人主页、修改密码、浏览记录、我的收藏、常见问题、意见反馈、关于我们等界面及对应功能实现。   另外还提供小程序开发基础知识讲解课程,包括小程序开发基础知识、组件封装、常用接口组件使用及常用功能实现等内容,具体如…

(1分钟速览)g2o入门指南--笔记版

在slam后端中,优化的框架很多,有ceres,g2o,gtsam这些。要想真正掌握slam后端的优化内容,这些框架是必不可少的上手练习的内容。本文则介绍有关g2o的相关内容,作为一个入门指南,目标:…

Python 学习 2022.08.28 周日

文章目录 一、 概述1.1) 之前写的文章:1.2) 基础点1.3) 配置1.4) Python2 和 Python3 的区别1.5) 相关问题跟踪解决1.6) 其他 一、 概述 1.1) 之前写的文章: 【Python大系】Python快速教程《Python 数据库 GUI CGI编…

怎么取消只读模式?硬盘进入只读模式怎么办?

案例:电脑磁盘数据不能修改怎么办? 【今天工作的时候,我想把最近的更新的资料同步到电脑上的工作磁盘,但是发现我无法进行此操作,也不能对磁盘里的数据进行改动。有没有小伙伴知道这是怎么一回事?】 在使…