答:指一次大的操作由不同的小操作组成的,这些小的操作分布在不同的服务器上,分布式事务需要保证这些小操作要么全部成功,要么全部失败。从本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
总结:其实上面两种场景,归根到底是要操作多数据库,并且要保证数据的一致性,而产生的分布式事务的。
XA实现分布式事务的原理如下:
1、同步阻塞问题:执行过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。
2、单点故障:由于(事务管理器)协调者的重要性,一旦协调者发生故障。(本地资源管理器)参与者会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。(如果是协调者挂掉,可以重新选举一个协调者,但是无法解决因为协调者宕机导致的参与者处于阻塞状态的问题)
3、数据不一致:在二阶段提交的阶段二中,当协调者向参与者发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中协调者发生了故障,这会导致只有一部分参与者接收到了commit请求。而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器无法执行事务提交。于是整个分布式系统便出现了数据不一致的现象。
4、二阶段无法解决的问题:参与者在发出commit消息之后宕机,而唯一接收到这条消息的协调者同时也宕机了。那么即使协调者通过选举协议产生了新的协调者,这条事务的状态也是不确定的,没人知道事务是否被已经提交了。
3PC分为三个阶段:CanCommit、PreCommit、DoCommit
- 事务询问:协调者向参与者发送CanCommit请求。询问是否可以执行事务提交操作。然后开始等待参与者的响应
- 响应反馈:参与者接到CanCommit请求之后,正常情况下,如果其自身认为可以顺利执行事务,则返回Yes响应,并进入预备状态。否则返回No
- 假如协调者从所有的参与者获得的反馈都是Yes,那么就会执行事务的与执行。
- 发送预提交请求:协调者向参与者发送PreCommit请求,并进入Prepared阶段。
- 事务预提交:参与者接收到PreCommit请求后,会执行事务操作,并将undo和redo信息记录到事务日志中。
- 响应反馈:如果参与者成功的执行了事务操作,则返回ACK响应,同时开始等待最终指令。
- 假如有任何一个参与者向协调者发送了No响应,或者等待超时,或者协调者都没有接到参与者的响应,那么就执行事务的中断。
- 发送中断请求:协调者向所有参与者发送abort请求。
- 中断事务:参与者收到来自协调者的abort请求之后(或超时之后,仍未收到协调者的请求),执行事务的中断。
- 执行提交
- 发送提交请求:协调接收到参与者发送的ACK响应,那么将从预提交状态进入到提交状态。并向所有参与者发送doCommit请求。
- 事务提交:参与者接收到doCommit请求之后,执行正式的事务提交,并在完成事务提交之后释放所有事务资源。
- 响应反馈:事务提交完之后,向协调者发送ACK响应。
- 完成事务:协调者接收到所有参与者的ACK响应之后,完成事务。
- 中断事务
- 协调者没有接收到参与者发送的ACK响应(可能是接受者发送的不是ACK响应,也可能响应超时),那么就会执行中断事务。
- 发送中断请求:协调者向所有参与者发送abort请求
- 事务回滚:参与者接收到abort请求之后,利用其在阶段二记录的undo信息来执行事务的回滚操作,并在完成回滚之后释放所有的事务资源。
- 反馈结果:参与者完成事务回滚之后,像协调者发送ACK消息。
- 中断事务:协调者接收到参与者反馈的ACK消息之后,执行事务的中断。
- 协调者没有接收到参与者发送的ACK响应(可能是接受者发送的不是ACK响应,也可能响应超时),那么就会执行中断事务。
- Try阶段:主要是对业务系统做检测及资源预留。
- Confirm阶段:确认执行业务操作。
- Cancel阶段:取消执行业务操作。
try、confirm、cancel三个操作。
步骤如下:
1、:服务A向消息中间件发送一条预备消息。
2、消息中间件保存预备消息并返回成功。
3、服务A执行本地事务。
4、服务A发送提交消息给消息中间件,服务B接收到消息之后执行本地事务。
以上几个步骤可能存在异常情况,现在对其进行分析:
步骤一出错:则整个事务失败,不会执行服务A的本地操作。
步骤二出错:则整个事务失败,不会执行服务A的本地操作。
步骤三出错:需要做回滚预备消息,由服务A实现一个消息中间件的回调接口,消息中间件会不断执行回调接口,检查服务A事务执行是否执行成功,如果失败则回滚预备消息。
步骤四出错:这个时候服务A的本地事务是成功的,但是消息中间件不需要回滚,其实通过回调接口,消息中间件能够检查到服务A执行成功了,这个时候其实不需要服务发提交消息了,消息中间件可以自己对消息进行提交,从而完成整个消息事务。
参考文章:
1、https://www.cnblogs.com/xifenglou/p/8440836.html
2、https://blog.csdn.net/skyie53101517/article/details/80741868
3、https://www.cnblogs.com/zcjcsl/p/7989792.html
来源:博客园
作者:胡金水
链接:https://www.cnblogs.com/hujinshui/p/11482208.html