赞
踩
目录
在分布式架构中,一般会有很多微服务与数据源,当程序对不同的微服务或数据源进行业务操作的时候,就需要所有的操作保证业务的原子性, 而不同的微服务有可能会出现问题而导致事务问题出现
CAP定理是1998年,加州大学的计算机科学家 Eric Brewer 提出,分布式系统有三个指标。
而这三个指标不可能同时做到。这个结论就叫做 CAP 定理。
Consistency(一致性):
用户访问分布式系统中的任意节点,得到的数据必须一致。
Availability(可用性):
用户访问集群中的任意健康节点,必须能得到响应,而不是超时或拒绝。
Partition tolerance (分区容错性):
因为网络故障或其它原因导致分布式系统中的部分节点与其它节点失去连接,形成独立分区。在集群出现分区时,整个系统也要持续对外提供服务
为什么说CAP定理不能同时满足:
分布式系统中,微服务一定会有概率出现单点故障, 此时就会出现 分区问题 ,而我们如果要保证 一致性 , 就要等待微服务修复,再让分布式系统对外提供服务,此时就导致 可用性 无法满足, 如果要保证 可用性 ,就会导致单点故障的那台微服务与其他微服务出现 一致性 问题.
BASE理论是对CAP的一种解决思路,包含三个思想:
Basically Available (基本可用):
分布式系统在出现故障时,允许损失部分可用性,即保证核心可用。
Soft State(软状态):
在一定时间内,允许出现中间状态,比如临时的不一致状态。
Eventually Consistent(最终一致性):
虽然无法保证强一致性,但是在软状态结束后,最终达到数据一致。
根据CAP定理和BASE理论我们可以用两种模式解决问题
AP模式(高可用,低一致):
各子事务分别执行和提交,允许出现结果不一致,然后采用弥补措施恢复数据即可,实现最终一致,可以保证服务的高可用
CP模式(高一致,低可用):
各子事务执行后互相等待,同时提交,同时回滚,达到数据的高一致性,但会牺牲服务的可用性
两种模式都需要在子事务之间互相通信,才能实现事务的协调,所以需要一个事务协调器(TC),每个子事务被称为分支事务,它们在一起被称为全局事务;
Seata框架是阿里巴巴开源出的一款分布式事务管理的组件 Seata官网
它的事务管理是由这三个角色配合工作实现的:
TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。
TM (Transaction Manager) - 事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务。
RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
Seata基于上述架构提供了四种不同的分布式事务解决方案:
XA模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入
AT模式:最终一致的分阶段事务模式,无业务侵入,也是Seata的默认模式
TCC模式:最终一致的分阶段事务模式,有业务侵入
SAGA模式:长事务模式,有业务侵入
XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准,XA 规范 描述了全局的TM与局部的RM之间的接口,几乎所有主流的数据库都对 XA 规范 提供了支持, XA分为两个阶段:
一阶段: 事务协调者通知每个事物参与者执行本地事务 ,本地事务执行完成后报告事务执行状态给事务协调者,此时事务不提交,继续持有数据库锁
二阶段: 事务协调者基于一阶段的报告来判断下一步操作 如果一阶段都成功,则通知所有事务参与者,提交事务 如果一阶段任意一个参与者失败,则通知所有事务参与者回滚事务
正常情况:
异常情况:
Seata框架对AT模式进行了封装以适应自己的架构模型
RM一阶段的工作:
注册分支事务到TC , 执行分支业务sql但不提交 , 报告执行状态到TC
TC二阶段的工作:
TC检测各分支事务执行状态 .如果都成功,通知所有RM提交事务 如果有失败,通知所有RM回滚事务
RM二阶段的工作:
接收TC指令,提交或回滚事务
XT模式的优缺点:
优点:
业务是高一致性,满足原子性, 常用数据库都支持,使用简单,没有代码侵入
缺点:
一阶段事务挟持数据库锁,只有到二阶段才会释放,效率较低,依赖数据库的事务支持,一些数据库不支持的话,就没法用,比如redis,mongoDB(4.0版本之前)
如何实现:
Seata的starter已经完成了XA模式的自动装配,有两种方式实现:
1) 修改application.yml文件(每个参与事务的微服务),开启XA模式:
seata: data-source-proxy-mode: XA2) 给发起全局事务的入口方法添加@GlobalTransactional注解
AT模式(Seata框架默认为AT模式)同样是分阶段提交的事务模型,不过缺弥补了XA模型中资源锁定周期过长的缺陷, 增加一个快照功能.
阶段一RM的工作:
注册分支事务 记录undo-log(数据快照) 执行业务sql并提交 向TC报告事务状态
( 业务成功 )阶段二进行提交时RM的工作:
删除undo-log(数据快照)
( 业务失败 )阶段二回滚时RM的工作:
根据undo-log恢复数据到更新前
流程图:
AT模式与XT模式的区别:
XT模式是在一阶段不提交事务, 锁定资源,而AT模式是在一阶段提交事务,释放资源
XT模式依赖数据库机制进行数据回滚,AT模式是根据数据快照(undo-log)进行数据回滚
XT模式是强一致性,而AT模式是最终一致性
AT模式的优缺点:
优点:
在一阶段就会提交事务而不锁定资源, 性能有所提升
没有代码侵入,框架会自动化执行
缺点:
两阶段之间是软状态,属于最终一致性
额外需要记录数据快照(undo-log),对性能有所损耗
实现AT模式:
需要在数据库创建一个undo_log数据快照表
修改application.yml文件(每个参与事务的微服务),开启AT模式:
seata: data-source-proxy-mode: AT
AT模式在一阶段就会提交事务,但如果在高并发场景下,就会出现脏读现象
解决思路就是引入了全局锁的概念。在释放DB锁之前,先拿到全局锁。避免同一时刻有另外一个事务来操作当前数据。
TCC模式与AT模式非常相似,每阶段都是独立事务,不同的是TCC通过人工编码来实现数据恢复。需要实现三个方法:
Try:资源的检测和预留;
Confirm:完成资源操作业务( 提交 );要求 Try 成功 Confirm 一定要能成功。
Cancel:预留资源释放( 回滚 ),可以理解为try的反向操作。
TCC的优点:
一阶段完成直接提交事务,释放数据库资源,性能好 相比AT模型,无需生成快照,无需使用全局锁,性能最强 不依赖数据库事务,而是依赖补偿操作,可以用于非事务型数据库
TCC的缺点:
有代码侵入,需要人为编写try、Confirm和Cancel接口,太麻烦 而且是软状态,事务是最终一致 需要考虑Confirm和Cancel的失败情况,需要做幂等性处理
空回滚:
当某分支事务的try阶段阻塞时,可能导致全局事务超时而触发二阶段的cancel操作。在未执行try操作时先执行了cancel操作,这时cancel就要空回滚。代码实现时,我们应该在执行cancel的时候对try进行判断,若try还未执行就要执行空回滚
业务悬挂:
对于已经空回滚的业务,之前被阻塞的try操作恢复,继续执行try,就永远不可能confirm或cancel ,事务一直处于中间状态,这就是业务悬挂。执行try操作时,应当判断cancel是否已经执行过了,如果已经执行,应当阻止空回滚后的try操作,避免悬挂
TCC实现:
TCC的Try、Confirm、Cancel方法都需要在接口中基于注解来声明,
@LocalTCC public interface AccountTCCService { //@TwoPhaseBusinessAction注解用来标注try //name属性 : try //commitMethod属性 : Confirm //rollbackMethod属性 : cancel @TwoPhaseBusinessAction(name = "deduct", commitMethod = "confirm", rollbackMethod = "cancel") void deduct(@BusinessActionContextParameter(paramName = "userId") String userId, @BusinessActionContextParameter(paramName = "money")int money); //@BusinessActionContextParameter注解用于将参数封装到上下文对象中 boolean confirm(BusinessActionContext ctx); boolean cancel(BusinessActionContext ctx); }
介绍:
Saga 模式是 Seata 即将开源的长事务解决方案,将由蚂蚁金服主要贡献。其理论基础是Hector & Kenneth 在1987年发表的论文Sagas。
Seata官网对于Saga的指南:Seata Saga 模式
原理:
在 Saga 模式下,分布式事务内有多个参与者,每一个参与者都是一个冲正补偿服务,需要用户根据业务场景实现其正向操作和逆向回滚操作。
分布式事务执行过程中,依次执行各参与者的正向操作,如果所有正向操作均执行成功,那么分布式事务提交。如果任何一个正向操作执行失败,那么分布式事务会去退回去执行前面各参与者的逆向回滚操作,回滚已提交的参与者,使分布式事务回到初始状态。
Saga也分为两个阶段:
一阶段:直接提交本地事务
二阶段:成功则什么都不做;失败则通过编写补偿业务来回滚
优点:
事务参与者可以基于事件驱动实现异步调用,吞吐高 一阶段直接提交事务,无锁,性能好 不用编写TCC中的三个阶段,实现简单
缺点:
软状态持续时间不确定,时效性差 没有锁,没有事务隔离,会有脏写
适用于微服务调用链路较长,业务较复杂,或者跨公司的业务,比如银行的转账
我们从以下几个方面来对比四种实现:
一致性:能否保证事务的一致性?强一致还是最终一致?
隔离性:事务之间的隔离性如何?
代码侵入:是否需要对业务代码改造?
性能:有无性能损耗?
场景:常见的业务场景
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。