Spring Cloud Alibaba: Seata - 分布式事务解决方案

官方网站:http://seata.io/zh-cn/
文档地址:http://seata.io/zh-cn/docs/overview/what-is-seata.html

一、什么是事务

事务指的就是一个操作单元,在这个操作单元中的所有操作最终要保持一致的行为,要么所有操作都成功,要么所有的操作都被撤销。简单地说,事务提供一种“要么什么都不做,要么做全套”机制。

二、本地事务

本地事物其实是数据库提供的事务机制。数据库管理系统中事务(transaction)的四个特性:简称ACID

  • A:原子性(Atomicity),一个事务中的所有操作,要么全部完成,要么全部不完成

  • C:一致性(Consistency),在一个事务执行之前和执行之后数据库都必须处于一致性状态

  • I:隔离性(Isolation),在并发环境中,当不同的事务同时操作相同的数据时,事务之间互不影响

  • D:持久性(Durability),指的是只要事务成功结束,它对数据库所做的更新就必须永久的保存下来

数据库事务在实现时会将一次事务涉及的所有操作全部纳入到一个不可分割的执行单元,该执行单元中的所有操作要么都成功,要么都失败,只要其中任一操作执行失败,都将导致整个事务的回滚

三、分布式事务

分布式事务指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。

由于分库分表、SOA架构、微服务架构的出现,不同的应用模块、不同的服务可能存在于不同的系统之上,他们会分别调用不同的数据库,传统的ACID已经无法实现事务控制了,所以需要使用分布式事务保障这些不同的操作的事务性。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。

可以将分布式事务简单理解为 要在分布式系统中实现的事务,可以将分布式事务看成是由多个本地事务组合而成的一个大的事务。

扫描二维码关注公众号,回复: 12561180 查看本文章

3.1 CAP理论

由于对系统或者数据进行了拆分,我们的系统不再是单机系统,而是分布式系统,针对分布式系统的CAP原理包含如下三个元素:

  • C:Consistency 一致性:在分布式系统中的所有数据 备份,在同一时刻具有同样的值,所有节点在同一时刻读取的数据都是最新的数据副本(例如:Redis主从复制)

  • A:Availability 可用性:好的响应性能。完全的可用性指的是在任何故障模型下,服务都会在有限的时间内处理完成并进行响应(例如:Ngnix+tomcat负载均衡)

  • P: Partition tolerance 分区容忍性:尽管网络上有部分消息丢失,但系统仍然可继续工作

CAP原理指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。因此在进行分布式架构设计时,必须做出取舍。而对于分布式数据系统,分区容忍性是基本要求,否则就失去了价值,所以一般而言P是必须要满足的(即可以容忍宕机或者网络故障,因为P是大概率事件,有些情况不可避免)。因此设计分布式数据系统,就是在一致性和可用性之间取一个平衡。(分布式系统中,网络出现故障,不可能同时保持一致性+可用性)。

对于大多数web应用,其实并不需要强一致性,因此牺牲一致性而换取高可用性,是目前多数分布式数据库产品的方向。 当然,牺牲一致性,并不是完全不管数据的一致性,否则数据是混乱的,那么系统可用性再高分布式再好也没有了价值。牺牲一致性,只是不再要求关系型数据库中的强一致性,而是只要系统能达到最终一致性即可,考虑到客户体验,这个最终一致的时间窗口,要尽可能的对用户透明,也就是需要保障“用户感知到的一致性”。通常是通过数据的多份异步复制来实现系统的高可用和数据的最终一致性的,“用户感知到的一致性”的时间窗口则取决于数据复制到一致状态的时间。

3.2 Base理论

BASE理论是指,Basically Available(基本可用)、Soft-state( 软状态/柔性事务)、Eventual Consistency(最终一致性)。是基于CAP定理演化而来,是对CAP中一致性和可用性权衡的结果。
核心思想:即使无法做到强一致性,但每个业务根据自身的特点,采用适当的方式来使系统达到最终一致性。

  1. 基本可用:指分布式系统在出现故障的时候,允许损失部分可用性,保证核心可用。但不等价于不可用。比如:搜索引擎0.5秒返回查询结果,但由于故障,2秒响应查询结果;网页访问过大时,部分用户提供降级服务等。

  2. 软状态:软状态是指允许系统存在中间状态,并且该中间状态不会影响系统整体可用性。即允许系统在不同节点间副本同步的时候存在延时。

  3. 最终一致性:系统中的所有数据副本经过一定时间后,最终能够达到一致的状态,不需要实时保证系统数据的强一致性。最终一致性是弱一致性的一种特殊情况。BASE理论面向的是大型高可用可扩展的分布式系统,通过牺牲强一致性来获得可用性。ACID是传统数据库常用的概念设计,追求强一致性模型。

3.3 柔性事务和刚性事务

柔性事务满足BASE理论(基本可用,最终一致),刚性事务满足ACID理论。

四、分布式事务解决方案

4.1 2PC(Two-phase commit protocol),二阶段提交协议

二阶段提交这种解决方案属于牺牲了一部分可用性来换取的一致性。二阶段提交是一种强一致性设计,2PC 引入一个事务协调者的角色来协调管理各参与者(也可称之为各本地资源)的提交和回滚,二阶段分别指的是准备(投票)和提交两个阶段。

  • 第一阶段(Try): 准备阶段:协调者向参与者发起指令,参与者评估自己的状态,如果参与者评估指令可以完成,则会写redo或者undo日志,让后锁定资源,执行操作,但并不提交。

  • 第二阶段(Commit/Cancel):如果每个参与者明确返回准备成功,则协调者向参与者发送提交指令,参与者释放锁定的资源,如何任何一个参与者明确返回准备失败,则协调者会发送中指指令,参与者取消已经变更的事务,释放锁定的资源。

两阶段提交方案应用非常广泛,几乎所有商业OLTP数据库都支持XA协议。但是两阶段提交方案锁定资源时间长,对性能影响很大,基本不适合解决微服务事务问题。

优点:

  • 尽量保证了数据的强一致,适合对数据强一致要求很高的关键领域。(其实也不能100%保证强一致)

缺点:

  • 实现复杂,延迟了提交时间,加长了资源阻塞时间,牺牲了可用性,对性能影响较大,不适合高并发高性能场景
  • 如果协调者宕机(单点),参与者没有协调者指挥,则会一直阻塞或者出现数据不一致的情况,并不能完全保证数据一致性。

4.2 3PC(Three-PhaseCommit),三段提交协议

阶段提交协议是两阶段提交协议的改进版本。相比于 2PC 它在参与者中引入了超时机制,它通过超时机制解决了阻塞的问题,并且三段提交协议在2pc的基础上增加了一个询问阶段(第一阶段),确认网络,避免阻塞, 使得参与者可以利用这一个阶段统一各自的状态,二三阶段就是上面的2pc。

三个阶段:

  • 询问阶段(CanCommit):协调者询问参与者是否可以完成指令,协调者只需回答是还是不是,而不需要做真正的操作,这个阶段超时导致中止

  • 准备阶段(PreCommit ):如果在询问阶段所有的参与者都返回可以执行操作,协调者向参与者发送预执行请求,然后参与者写redo和undo日志,执行操作,但是不提交操作;如果在询问阶段任何参与者返回不能执行操作的结果,则协调者向参与者发送中止请求,这里的逻辑与两阶段提交协议的的准备阶段是相似的,这个阶段超时导致成功

  • 提交阶段(DoCommit):如果每个参与者在准备阶段返回准备成功,也就是预留资源和执行操作成功,协调者向参与者发起提交指令,参与者提交资源变更的事务,释放锁定的资源;如果任何一个参与者返回准备失败,也就是预留资源或者执行操作失败,协调者向参与者发起中止指令,参与者取消已经变更的事务,执行undo日志,释放锁定的资源,这里的逻辑与两阶段提交协议的提交阶段一致

4.3 消息中间件的可靠消息服务

基于可靠消息服务的方案是通过消息中间件保证上、下游应用数据操作的一致性。假设有A和B两个系统,分别可以处理任务A和任务B。此时存在一个业务流程,需要将任务A和任务B在同一个事务中处理。就可以使用消息中间件来实现这种分布式事务。
在这里插入图片描述

第一步:消息由系统A投递到中间件

在系统A处理任务A前,首先向消息中间件发送一条消息

消息中间件收到后将该条消息持久化,但并不投递。持久化成功后,向A回复一个确认应答

系统A收到确认应答后,则可以开始处理任务A

任务A处理完成后,向消息中间件发送Commit或者Rollback请求。该请求发送完成后,对系统A而言,该事务的处理过程就结束了

如果消息中间件收到Commit,则向B系统投递消息;如果收到Rollback,则直接丢弃消息。但是如果消息中间件收不到Commit和Rollback指令,那么就要依靠"超时询问机制"。

超时询问机制:

系统A除了实现正常的业务流程外,还需提供一个事务询问的接口,供消息中间件调用。当消息中间件收到发布消息便开始计时,如果到了超时没收到确认指令,就会主动调用系统A提供的事务询问接口询问该系统目前的状态。该接口会返回三种结果,中间件根据三种结果做出不同反应:

提交:将该消息投递给系统B

回滚:直接将条消息丢弃

处理中:继续等待

第二步:消息由中间件投递到系统B

消息中间件向下游系统投递完消息后便进入阻塞等待状态,下游系统便立即进行任务的处理,任务处理完成后便向消息中间件返回应答。

  • 如果消息中间件收到确认应答后便认为该事务处理完毕

  • 如果消息中间件在等待确认应答超时之后就会重新投递,直到下游消费者返回消费成功响应为止。

一般消息中间件可以设置消息重试的次数和时间间隔,如果最终还是不能成功投递,则需要手工干预。这里之所以使用人工干预,而不是使用让A系统回滚,主要是考虑到整个系统设计的复杂度问题。

基于可靠消息服务的分布式事务,前半部分使用异步,注重性能;后半部分使用同步,注重开发成本。

4.4 本地消息表

本地消息表其实就是利用了 各系统本地的事务来实现分布式事务。

本地消息表顾名思义就是会有一张存放本地消息的表,一般都是放在数据库中,然后在执行业务的时候 将业务的执行和将消息放入消息表中的操作放在同一个事务中,这样就能保证消息放入本地表中业务肯定是执行成功的。

然后再去调用下一个操作,如果下一个操作调用成功了好说,消息表的消息状态可以直接改成已成功。

如果调用失败也没事,会有 后台任务定时去读取本地消息表,筛选出还未成功的消息再调用对应的服务,服务更新成功了再变更消息的状态。

这时候有可能消息对应的操作不成功,因此也需要重试,重试就得保证对应服务的方法是幂等的,而且一般重试会有最大次数,超过最大次数可以记录下报警让人工处理。

可以看到本地消息表其实实现的是最终一致性,容忍了数据暂时不一致的情况。

4.5 最大努力通知

最大努力通知也被称为定期校对,其实是对第二种解决方案的进一步优化。它引入了本地消息表来记录错误消息,然后加入失败消息的定期校对功能,来进一步保证消息会被下游系统消费。

在这里插入图片描述

第一步:消息由系统A投递到中间件

处理业务的同一事务中,向本地消息表中写入一条记录

准备专门的消息发送者不断地发送本地消息表中的消息到消息中间件,如果发送失败则重试

第二步:消息由中间件投递到系统B

消息中间件收到消息后负责将该消息同步投递给相应的下游系统,并触发下游系统的任务执行

当下游系统处理成功后,向消息中间件反馈确认应答,消息中间件便可以将该条消息删除,从而该事务完成

对于投递失败的消息,利用重试机制进行重试,对于重试失败的,写入错误消息表

消息中间件需要提供失败消息的查询接口,下游系统会定期查询失败消息,并将其消费

这种方式的优缺点:

优点: 一种非常经典的实现,实现了最终一致性。

缺点: 消息表会耦合到业务系统中,如果没有封装好的解决方案,会有很多杂活需要处理。

4.6 TCC事务

TCC即为Try Confifirm Cancel,它属于补偿型分布式事务。TCC实现分布式事务一共有三个步骤:

  • Try: 尝试待执行的业务:这个过程并未执行业务,只是完成所有业务的一致性检查,并预留好执行所需的全部资源

  • Confifirm: 确认执行业务:确认执行业务操作,不做任何业务检查, 只使用Try阶段预留的业务资源。通常情况下,采用TCC则认为 Confifirm阶段是不会出错的。即:只要Try成功,Confifirm一定成功。若Confifirm阶段真的出错了,需引入重试机制或人工处理。

  • Cancel: 取消待执行的业务:取消Try阶段预留的业务资源。通常情况下,采用TCC则认为Cancel阶段也是一定成功的。若Cancel阶段- 真的出错了,需引入重试机制或人工处理

在这里插入图片描述
在这里插入图片描述

TCC两阶段提交与XA两阶段提交的区别是:

  • XA是资源层面的分布式事务,强一致性,在两阶段提交的整个过程中,一直会持有资源的锁。

  • TCC是业务层面的分布式事务,最终一致性,不会一直持有资源的锁。

TCC事务的优缺点:

  • 优点:把数据库层的二阶段提交上提到了应用层来实现,规避了数据库层的2PC性能低下问题。

  • 缺点:TCC的Try、Confifirm和Cancel操作功能需业务提供,开发成本高。

五、Alibaba 分布式事务解决方案Seata

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

5.1 Seata

Seata 主要由三个重要组件组成:

  • TC:Transaction Coordinator 事务协调器,管理全局的分支事务的状态,用于全局性事务的提交和回滚。

  • TM:Transaction Manager 事务管理器,用于开启、提交或者回滚全局事务。

  • RM:Resource Manager 资源管理器,用于分支事务上的资源管理,向TC注册分支事务,上报分支事务的状态,接受TC的命令来提交或者回滚分支事务。
    在这里插入图片描述
    Seata的执行流程如下:

A服务的TM向TC申请开启一个全局事务,TC就会创建一个全局事务并返回一个唯一的XID

A服务的RM向TC注册分支事务,并及其纳入XID对应全局事务的管辖

A服务执行分支事务,向数据库做操作

A服务开始远程调用B服务,此时XID会在微服务的调用链上传播

B服务的RM向TC注册分支事务,并将其纳入XID对应的全局事务的管辖

B服务执行分支事务,向数据库做操作

全局事务调用链处理完毕,TM根据有无异常向TC发起全局事务的提交或者回滚

TC协调其管辖之下的所有分支事务, 决定是否回滚

Seata实现2PC与传统2PC的差别:

架构层次方面,传统2PC方案的 RM 实际上是在数据库层,RM本质上就是数据库自身,通过XA协议实现,而
Seata的RM是以jar包的形式作为中间件层部署在应用程序这一侧的。

两阶段提交方面,传统2PC无论第二阶段的决议是commit还是rollback,事务性资源的锁都要保持到Phase2完成才释放。而Seata的做法是在Phase1
就将本地事务提交,这样就可以省去Phase2持锁的时间,整体提高效率

5.2 TCC 模式

回顾总览中的描述:一个分布式的全局事务,整体是 两阶段提交 的模型。全局事务是由若干分支事务组成的,分支事务要满足 两阶段提交 的模型要求,即需要每个分支事务都具备自己的:

一阶段 prepare 行为
二阶段 commit 或 rollback 行为
在这里插入图片描述

根据两阶段行为模式的不同,我们将分支事务划分为 Automatic (Branch) Transaction Mode 和 Manual (Branch) Transaction Mode.

AT 模式: 基于 支持本地 ACID 事务 的 关系型数据库:

  • 一阶段 prepare 行为:在本地事务中,一并提交业务数据更新和相应回滚日志记录。
  • 二阶段 commit 行为:马上成功结束,自动 异步批量清理回滚日志。
  • 二阶段 rollback 行为:通过回滚日志,自动 生成补偿操作,完成数据回滚。

TCC 模式: 不依赖于底层数据资源的事务支持:

  • 一阶段 prepare 行为:调用 自定义 的 prepare 逻辑。
  • 二阶段 commit 行为:调用 自定义 的 commit 逻辑。
  • 二阶段 rollback 行为:调用 自定义 的 rollback 逻辑。

所谓 TCC 模式,是指支持把 自定义 的分支事务纳入到全局事务的管理中。

5.3 Saga 模式

Saga模式是SEATA提供的长事务解决方案,在Saga模式中,业务流程中每个参与者都提交本地事务,当出现某一个参与者失败则补偿前面已经成功的参与者,一阶段正向服务和二阶段补偿服务都由业务开发实现。

Saga模式示意图:
在这里插入图片描述

六、Alibaba Seata 实践

猜你喜欢

转载自blog.csdn.net/u014553029/article/details/113688004