1.什么是分布式事务?为什么要使用分布式事务?

分布式事务就是把分布在不同数据库的操作视为同一组事务进行管理,和本地事务相同,既然是同一组事务那么就需要满足原子性,要么全部成功,要么全部回滚。
因为我们在本地事务的时候会去考虑ACID的问题,可是带入到不同数据库,不同服务器上则回滚不了别的数据库。所以这个时候就需要使用到分布式事务的思想,把它们作为一个整体进行管理。

2.分布式事务常见的实现思想有哪些?

1.2PC/3PC….
2PC就是两段式提交。何为两段式提交?就是把所有不同服务的事务作为一个个子事务,交由一个事务管理器进行管理,一阶段,管理器给子事务发送prepare消息,查询时候准备好提交,根据子事务的回复来决定二阶段是commit还是回滚。二阶段,管理器给子事务发送commit或者回滚指令。
需要注意的是,传统的2PC思想有很大的问题。其一,管理器必须等到所有服务都确认状态以后,才能执行二阶段,如果某个子事物出了问题,那就会一直占用资源。其二,通过发送指令的方式也会有原子性的问题。试想一下,一阶段确认状态的时候,A事物还是好的,并回复了OK,当管理器发送commit指令的这段时间,A事物就出问题了,那带来的后果就是A事物并没有提交,而其他事物提交了,违背了事物的原子性。

2.TCC
基于补偿性事物的AP系统的一种实现,具有弱一致性。
优点是异步执行效率高
缺点是对代码的侵入性强。每个分支都必须去实现try,confirm,cacel三个操作,改造成本高,实现难度大。

3.Seata
Seata有两种实现方式,基于2PC实现和基于TCC实现
2PC实现的大致流程:
TC:事务协调器。相当于中间件,需要单独下载客户端
TM:事务管理器。
RM:资源管理器。负责分支事务,汇报状态,执行本地提交和回滚。

1.TM向TC发起申请开启一个全局事务,事务创建成功生成一个XID
2.RM像TC发起申请注册分支事务,并把自身事务id和XID进行绑定,纳入全局事务管理。
3.RM执行本地事务并记录undolog,提交本地事务,把是否提交成功的状态返回给TC
4.TM根据TC中每一个分支事物的状态,决定是提交还是全局回滚。如果有任意一个分支事物失败,都需要回滚。
回滚:各个分支事物根据自身的undolog日志进行回滚
提交:TM发送一个提交状态给各个分支事务,分支事务删除各自的undolog日志。

这种方式相较于传统的2PC方案,有两大好处。
1.TM不需要等待所有分支事务都执行完毕,各个分支事务在自身执行完成后就提交,并释放资源。不像传统方式,需要等到所有的都完成了再释放资源,效率更高。
2.因为各个分支事物都是执行完成后在本地直接提交,这样就保证了原子性,避免了某个分支事务提交失败,其他事务没有回滚的问题。

4.可靠消息最终一致性
可靠消息最终一致性就是不保证强一致性,而是保证最终一致性。
一般我们通过MQ消息中间件的方式来实现。
通过MQ我们需要解决三个问题:
1.事务与消息的原子性问题。
2.接受消息的可靠性。设置ack为手动签收,在业务代码执行完成后再手动签收。设置路由,队列,消息的持久化。
3.防止重复消费消息。要保证消息的幂等性。

常用方案通过RocketMQ实现。大致实现流程:
1.生产者发送一个半消息给消息队列,队列收到后返回一个状态给生产者。
2.生产者根据返回的消息执行。如果是成功就提交本地事务,并把提交的状态发送给消息队列。
3.消息队列收到状态,如果是成功,就把消息放到消费者监听的队列中。如果失败,就删除半消息。
4.如果消息队列很久都没有收到生产者返回的消息,应该主动去调用生产者提供的查询接口,查询是否成功状态。

可靠消息最终一致性适用于实时性要求不高的,如银行转账,赠送积分,赠送优惠券等。

5.最大努力通知
这个我们在使用支付宝三方支付的时候,支付宝有用到这个技术。如果我们支付成功了,支付宝会给我们发送一个消息,如果没收到,支付宝会在25小时内多次发送,如果还是没有接受到,就没有办法了,需要自己去支付宝提供的接口去查询。
一般用在用第三方的场合。