分布式事务解决方案

分布式事务解决方案,第1张

分布式事务解决方案 什么是分布式事务

分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。一个大的 *** 作由N个小得 *** 作共同完成,而这些小得 *** 作又分布在不同服务器上,针对这些小 *** 作,要么全部执行,要么全部不执行。

分布式理论 CAP理论

在一个分布式系统中,以下三点特征无法同时满足

一致性©:
在分布式系统中的所有数据备份,在同一时刻是否拥有相同的值。等同于所有结点访问同一份最新的数据副本

可用性(A):
在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求

分区容错性§:
即使出现单个组件无法可用, *** 作依然可以完成

一个web应用只能满足其中两个属性,显然任何横向扩展策略都要依赖于数据分区,因此设计人员必须在一致性与可用性之前做选择。

base理论

Basically Available 基本可用
Soft state 软状态
Eventually consistent 最终一致性

base理论是对CAP中的一致性与可用性进行一个权衡的结果,理论的核心思想就是:我们无法做到强一致性,但每个应用都可以根据自身业务特点采取适当地方式使得系统保持最终一致性。

分布式事务解决方案 两阶段提交(2pc)

mysql事务就是就是通过日志系统完成的两阶段提交。
两阶段提交协议可以用于单机集中式系统,由事务管理器协调多个资源管理器;也可以用于分布式系统,由一个全局的事务管理器协调各个子系统的局部事务管理器完成两阶段提交。

这个协议有两个角色,A结点是事务的协调者,B和C是事务的参与者。事务的提交分成两个阶段。

第一阶段是投票阶段
1.协调者首先将命令写入日志
2.分别发prepare命令给B和C
3.B和C收到命令后,根据自身情况告知协调者本身的事务是否可以被提交
4.将处理结果记录到日志,并返回给些调整


第二阶段是决定阶段
当A收到B和C的确认消息后判断是否全部的参与者都可以提交事务,如果可以则写入日志并且发起commit命令;否则则发起abort命令。

参与者收到命令便执行响应命令并记录日志同时返回给协调者结果

可能存在的问题

【单点故障】一旦事务管理器出现故障,整个系统不可用
【数据不一致】在阶段二,由于网络问题只有部分 参与者收到了commit消息
【响应时间长】整个消息链路是串行的,不适合高并发场景
【不确定性】当事务管理器发送commit之后,此时由于网络问题只有一个参与者收到了commit,此时该参与者与事务管理者同时宕机,新选举的事务管理器无法确定该消息是否提交成功

三阶段提交(3pc)

相对于2pc来说增加了canCommit阶段和超时机制。如果时间内没收到协调者的commit则会自动进行commit,解决2pc单点故障事务hang住问题。

但是性能问题以及不一致问题仍然没有解决

第一阶段:CanCommit阶段
协调者询问事务参与者是否有能力完成此次事务,如果都返回yes则进去第二阶段,否则协调者向所有参与者发送abort命令

第二阶段:PreCommit阶段
此时协调者向所有的参与者发送preCommit命令,参与者收到后开始执行事务,并记录undo log以及redo log.参与者执行完事务后(未提交状态)就会给协调者反馈ack代表我已经准备好提交了,然后等待协调者进一步命令。

第三阶段:DoCommit阶段
如果所有的参与者都返回ack,那么协调者会从预提交状态变为提交状态,然后向所有的参与者发送doCommit命令。参与者收到命令后提交事务并返回ack。

补偿事务(TCC)

TCC其实就是采用的补偿机制,其核心思想是针对每个 *** 作,都要注册一个与其对应的确认和补偿(撤销) *** 作。

它分为三个阶段:try、/confirm/i、cancel

Try阶段主要是对业务系统做检测以及资源预留
/confirm/i阶段主要是对业务系统做准确提交
Cancel阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放等 *** 作

以下订单减库存举例:

总之,TCC是通过代码人为实现了两阶段提交,不用业务所写的代码都不一样,并且很大程度增加了代码复杂度,所以这种模式并不能很好的被复用。

本地消息表


消息生产方需要额外建一个消息表,并记录消息发送的状态,消息表和业务表在一个事务中提交,并将消息发送给消息队列。整个流程在一个事务中,可以保证原子性。

消息消费方需要处理这个消息并完成自己的业务逻辑,如果是业务执行失败,可以给生产方发送一个业务补偿消息,通知生产方进行回滚。

生产方和消费方需要定时扫描本地消息表

消息事务

消息事务的原理是将两个事务通过消息中间件进行异步解耦,和上述本地消息表有点类似。本质就是将本地消息表封装到了消息队列中

比较适用于高并发的场景

最大努力通知

实现简单,适用于一些最终一致性要求低的场景
1.系统A执行完本地事务后,发送消息到MQ
2.有个专门消费MQ的服务消费消息并调B系统接口
3.B执行成功就成功,失败的话利用MQ不断重试,直到达到最大重试次数后放弃。

Sagas事务模型

每个Saga由一系列sub-transaction Ti组成。每个Ti都有对应的补偿动作Ci,补偿动作用于撤销Ti造成的结果。这里可以理解为,针对每一个分布式事务的每个执行 *** 作或者是步骤都是一个 Ti,例如扣减库存是T1、创建订单是T2、支付服务是T3。那么针对每个Ti都对应一个补偿动作Ci,例如回复库存C1、订单回滚C2、支付回滚C3

Saga事务有两种恢复策略

向前恢复(forward recovery),也就是“勇往直前”。
对于执行不通过的事务,会尝试重试事务,这里有一个假设就是每个子事务最终都会成功。这种方式适用于必须要成功的场景,子事务按照从左到右的顺序执行,T1执行完毕以后T2 执行,然后是T3、T4、T5。如果在执行T1的时候失败了就重试T1,以此类推在哪个子事务执行时失败了就执行哪个事务。因此叫做“勇往直前”。

向后恢复(backward recovery),在执行事务失败时,补偿所有已完成的事务,是“一退到底”的方式。子事务依旧从左往右执行,在执行到事务T3的时候,该事务执行失败了,于是按照红线的方向开始执行补偿事务,先执行C3、然后是C2和C1,直到T0、T1、T2的补偿事务C1、C2、C3都执行完毕。也就是回滚整个Saga的执行结果。

Saga分布式事务协调

如果在执行子事务的过程中遇到子事务对应的本地事务失败,则Saga会按照相反的顺序执行补偿事务。通常来说我们把这种Saga执行事务的顺序称为个Saga的协调逻辑。这种协调逻辑有两种模式,编排(Choreography)和控制(Orchestration)

编排(Choreography):参与者(子事务)之间的调用、分配、决策和排序,通过交换事件进行进行。是一种去中心化的模式,参与者之间通过消息机制进行沟通,通过监听器的方式监听其他参与者发出的消息,从而执行后续的逻辑处理。由于没有中间协调点,靠参与靠自己进行相互协调。


编排优点
简单:每个子事务进行 *** 作时只用发布事件消息,其他子事务监听处理。
松耦合:参与者(服务)之间通过订阅事件进行沟通,组合会更加灵活。

编排缺点

理解困难:没有对业务流程进行完整的描述,要了解整个事务的执行过程需要通过阅读代码完成。增加开发人员理解和维护代码的难度。

存在服务的循环依赖:由于通过消息和事件进行沟通,参与者之间会存在循环依赖的情况。也就是A服务调用B服务,B服务又调用A服务的情况。这也增加了架构设计的复杂度,在设计初期需要认真考虑。

紧耦合风险:每个参与者执行的方法都依赖于上一步参与者发出的消息,但是上一步的参与者的所有消息都需要被订阅,才能了解参与者的真实状态,无形中增加了两个服务的耦合度。

控制(Orchestration):Saga提供一个控制类,其方便参与者之前的协调工作。事务执行的命令从控制类发起,按照逻辑顺序请求Saga的参与者,从参与者那里接受到反馈以后,控制类在发起向其他参与者的调用。所有Saga的参与者都围绕这个控制类进行沟通和协调工作。


优点
避免循环依赖:在编排模式中存在参与者之间的循环调用,而中心控制类的方式可以避免这种情况的发生。

降低复杂性:所有事务交给控制器完成,它负责命令的执行和回复的处理,参与者只需要完成自身的任务,不用考虑处理消息的方式,降低参与者接入的复杂性。

容易测试:测试工作集中在集中控制类上,其他服务单独测试功能即可。

容易扩展:如果事务需要添加新步骤,只需修改控制类,保持事务复杂性保持线性,回滚更容易管理。

缺点
依赖控制器:控制器中集中太多逻辑的风险。

增加管理难度:这种模式除了管理各个业务服务以外,还需要额外管理控制类服务,无形中增加了管理的难度和复杂度。而且存在单点风险,一旦控制器出现问题,整个业务就处于瘫痪中。

分布式事务框架

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

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5655956.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存