vlambda博客
学习文章列表

分布式事务介绍和事务框架LCN,seata介绍

一.分布式事务发生的原因:

前提是: 服务为微服务架构,并且每个微服务对应的数据库不一样


假设有一个用户服务和一个订单服务,当用户下订单的时候,就会去请求订单服务接口,订单创建成功后,会去调用用户服务的接口,扣减用户账户余额,再扣除用户余额的时候可能因为网络波动会发生下面几种情况:


①调用扣余额接口报错,实际请求已经发给用户服务了,用户扣余额成功了,但是订单这边回滚了(这种情况简单来讲就是订单服务调用接口超时,就会有异常)


②调用用户余额接口成功了,实际请求没有发给用户服务,订单创建成功,用户余额未扣减.


二.分布式事务简单业务解决方法:

1.一阶段失败分为两种情况:

①实际请求未发送到接收方,这种情况直接根据异常回滚就好了

②实际请求已经发送到接收方(这种情况最难处理,下面会讲解事务框架的做法)


2.二阶段正常执行结果失败了,这种情况需要通知一阶段进行回滚


三.二阶段分布式事务框架:

1.事务管理器和本地资源管理器。其中本地资源管理器往往由数据库实现


2.阶段一为准备阶段:即所有的参与者准备执行事务并锁住需要的资源.参与者执行代码准备提交数据的时候,向事务管理器报告代码执行结果。


3.阶段二为提交阶段:事务管理器根据参与者报告的执行结果,来进行提交或者回滚消息.


总结:  
①事务执行阶段会一直占用着数据库资源不释放
②没有进行预校验
③事务管理器挂掉之后,会一直锁住数据库资源,不会释放


四.三阶段分布式事务框架:

比二阶段事务,多了一个代码执行前预校验,和事务管理器挂掉之后,有超时时间,到了之后都会提交事务


总结:事务执行阶段会一直占用着数据库资源不释放


五.LCN三阶段事务框架执行流程图:


六.阿里的seata:

1.seata的三个重要概念
①事务协调者(TC):

维护全局和分支事务的状态,驱动全局事务提交或回滚

(单独部署的seata服务端就是事务协调者)


②事务管理器(TM):

定义全局事务的范围:开始全局事务、提交或回滚全局事务。

(一开始全局事务接口的微服务就是TM)


③资源管理器(RM):

管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

(相当于每个微服务都有一个RM,把自己的状态注册到TC中)


2.可以通过注册中心部署集群模式,实现高可用的切换,同时事务分组的模式,也可以快速切换到另外一个事务集群.


3.执行流程:
一阶段:首先获取全局锁,执行事务代码成功后,直接把业务数据和回滚日志提交到数据库,释放数据库连接资源


二阶段:首先获取全局锁,获取到之后,执行事务代码成功,快速提交到异步队列中,批量提交到数据库中,执行代码失败,根据回滚日志,回滚一阶段提交的数据.


4.如何解决分布式事务中一阶段失败实际请求已经发送到接收方痛点的
①.接收端刚开始接收到请求的时候就需要获取到一阶段创建的全局锁,如果一阶段已经回滚,全局锁已经释放掉了,接收端获取不到


②接收端代码已经开始执行,走到数据库提交阶段,这个时候一阶段回滚,seata同时也会把接收端的数据回滚


5.seata回滚必须要有异常,没有异常上抛不会回滚


总结:
优点:从seata执行流程来看,他的性能优化,主要体现在一阶段释放数据库资源,二阶段提交异步快速化


七.用阿里MQ解决:

出现原因:
因为服务之间互相调用大多数都是http协议,而当调用另外一个服务接口的时候因为出现网络波动,造成发生异常回滚,可能另外一个服务已经收到消息,开始处理事物了,这就会造成脏数据


1.MQ普通消息:
用户用余额下订单流程:首先订单服务创建订单,并且直接提交事务,订单状态为未支付,然后订单服务里面需要订阅用户余额是否扣减成功的消息,接受到消息后,决定是否更改订单状态,然后发送扣减用户余额的MQ消息,当用户服务收到扣减余额消息后,开始执行扣减用户余额事务代码,并且把扣减余额结果发送mq消息给订单服务.用户扣减余额和订单状态修改,要做幂等设计

解决:
而阿里云MQ是用的TCP协议,所以首先他性能非常好,而且他本身发送MQ的时候会确认连接信息,然后在发送,在一定程度上解决了幂等问题.
发送方如果发送消息失败,并且没有异常抛出,就会造成事务不一致情况.解决方法: 这个时候要参考订单表设计状态字段: 未支付和已支付.


2.MQ事务消息:

上图的流程:

1.开始事务之前,首先发送半事务消息,半事务消息里面包含本次要发送给消息订阅方需要的信息.

2.此时消息发送方必须等待MQ服务端返回半事务消息发送成功之后才能提交本地事务

3.当消息发送方提交了本地事务之后,要像MQ服务端确认事务消息回滚还是提交,如果MQ服务端没有收到确认消息,会去消息发送方回查消息发送方事务执行状态

4.当像MQ服务端确认事务状态后,并且消息发送方本地事务执行成功,就会投递给消息订阅方事务消息


3.总结:

优点:
性能比较好,高并发场景适合用,因为他无论哪个阶段都没有长期占用数据库资源


缺点:
①可能修改库存或者用户余额的地方不止一个入口,seata可以暂时锁住其他入口,MQ方式没有办法做到

②开发消息业务代码麻烦

③消息订阅方需要做幂等设计,因为可能会重复发送MQ


八.分布式事务的问题专业名词解释


①空回滚:

意思就是在方法中还没有提交到数据库,发生了异常,这个时候事务方法需要回滚,这个时候就是空回滚因为数据库里面没有这条记录,

②幂等:

是发起方服务执行完业务代码后,在调用参与方服务的时候,结果发生了网络故障,然后参与方其实收到请求了,但是事物管理器认为网络故障,没收到请求,会再次尝试请求,重复调用参与方,简单来讲,就是会发生多次重复调用.

③悬挂:

发起方在调用参与方的时候,结果因为网络原因调用超时,就会通知TC回滚该分布式事务,可能回滚完成后,RPC请求才到达参与者,真正执行,从而造成悬挂