在分布式系统中,一个业务因为跨越不同数据库或者跨越不同微服务而包含多个子事务,要求所有子事务同时成功或失败,这就是分布式事务。
比如一个电商系统的下单操作需要请求三个服务来完成,这三个服务分别是:订单服务,账户服务,库存服务。
当订单生成完毕以后,就需要分别请求账户服务和库存服务进行进行账户余额的扣减和库存扣减。
假设都扣减成功了,此时在执行下单的后续操作时出现了问题,那么订单数据库就进行事务回滚,订单生成失败,而账户余额和扣减则都扣减成功了。
这就出现了问题,而分布式事务就是解决上述这种不一致问题的。
产生分布式事务的原因主要有下面几种:
在分布式系统有三个指标,分别是一致性、可用性、分区容错性
一致性(Consistency) : 分布式系统中的更新操作成功并返回客户端完成后,所有节点在同一时间的数据完全一致,不能存在中间状态
可用性(Availability) : 分布式系统中提供的服务必须一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果
分区容错性(Partition tolerance) : 分布式系统在遇到任何网络分区故障时,仍然需要能够保证对外提供满足一致性和可用性的服务
CAP定理是指这个三个指标最多可以同时满足两个
对于分布式系统而言,各节点之间一定会存在网络交互,首先网络存在延迟,其次无法100%确保网络的可用,因此可以认为分区网络故障不可避免。
在此条件下,如果要保证各节点的一致性,就必须在一个节点数据变更后同步给其他节点前,让客户等待,这就无法满足可用性
如果要保证各节点的可用性,就必须让各节点在接收到请求立即返回响应,那这个时候各节点可能还没有完成数据的统一,所以就违背了一致性
所以,在存在系统分区的场景下,可用性和一致性无法同时满足
BASE是CAP理论的延伸,核心思想是即使无法做到强一致性,但应用可以采用适合的方式达到最终一致性。它的思想包含三方面:
分布式事物的解决方案有很多,常见的有2PC、TCC,还有可以使用MQ来做
方案一:2PC
2PC即两阶段提交,它是一种保证强一致性的处理方式。 主要将事务分为两个阶段:
方案二:TCC
TCC又称补偿事务,它是一种保证最终一致性的处理方式,一共有三个步骤:
方案三:MQ分布式事务
如果数据强一致性要求没那么高,可以采用消息中间件(MQ)实现事务最终一致。
在支付系统中,常常使用的分布式事务解决方案就是基于MQ实现的,它对数据强一致性要求没那么高,但要求数据最终一致即可。
例如:向借呗申请借钱,借呗审核通过后支付宝的余额才会增加,但借呗和支付宝有可能不是同一个系统,这时候就可以借助MQ完成分布式事务
具体流程如下所示:
1、找借呗借钱
2、借呗借钱审核通过,同步生成借款单
3、借款单生成后,向MQ发送消息,通知支付宝转账
4、支付宝读取MQ消息,并增加账户余额
上图最复杂的其实是如何保障2、3在同一个事务中执行(本地事务和MQ消息发送在同一个事务执行),借款结束后,借呗数据处理就完成了,接下来支付宝才能读到消息,然后执行余额增加,这才完成整个操作。如果中途操作发生异常,例如支付宝余额增加发生问题怎么办?此时需要人工解决,没有特别好的办法,但这种事故概率极低。
Seata事务管理中有三个重要的角色:
1、TC (Transaction Coordinator) -事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。
2、TM (Transaction Manager) -事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务。
3、RM (Resource Manager) -资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
如下所示:
xa模式整个工作流程图如下所示:
分为两个阶段:
1、RM一阶段的工作:① 注册分支事务到TC ② 执行分支业务sql但不提交 ③ 报告执行状态到TC
2、TC二阶段的工作:TC检测各分支事务执行状态 ①如果都成功,通知所有RM提交事务 ②如果有失败,通知所有RM回滚事务
3、RM二阶段的工作:接收TC指令,提交或回滚事务
xa模式牺牲了可用性,保证了强一致性
at模式的整个工作流程图如下所示:
1、阶段一RM的工作:① 注册分支事务 ② 记录undo-log(数据快照)③ 执行业务sql并提交 ④报告事务状态
2、阶段二提交时RM的工作:删除undo-log即可
3、阶段二回滚时RM的工作:根据undo-log恢复数据到更新前
at模式牺牲了一致性,保证了可用性
TCC模式与AT模式非常相似,每阶段都是独立事务,不同的是TCC通过人工编码来实现数据恢复。需要实现三个方法:
1、Try:资源的检测和预留;
2、Confirm:完成资源操作业务;要求 Try 成功 Confirm 一定要能成功。
3、Cancel:预留资源释放,可以理解为try的反向操作。
Seata中的tcc模型的执行流程如下所示:
1、阶段一RM的工作:① 注册分支事务 ② 执行try操作预留资源 ④报告事务状态
2、阶段二提交时RM的工作:根据各分支事务的状态执行confirm或者cancel