分布式事物:
\
2PC(基于数据库XA和阿里的Seata)、3PC、TCC、本地消息表、MQ事务消息等
\
1、基于XA的两阶段提交
TM发送多个sql到数据库上,此时不提交,如果多个都执行成功了,就统一commit,否则就rollback
缺点:
1、需要数据库支持XA协议
2、性能比较慢,因为需要全部执行成功了才commit
3、commit可能会丢失
\
\
3PC在上面多了一层 探测请求,确保各个RM是否存活,并且在TM引入了超时机制,总的来说3PC提高了可用性,通过探测和超时提高可用性,但是性能依旧有问题
\
2、阿里的seata,也是基于2PC
TC:事务协调者 单独部署,管理全局事务
TM:事务管理者 事务发起者,做事务回滚和commi
RM:资源管理者 单个资源拥有者
1、TM发起事务,和TC申请事务ID,然后TM根据事务ID像所有RM发起分布式事务,所有RM去执行逻辑,并且直接commit和写入undo log的sql,便于出错回滚;如果全部执行成功那就成功了,有一个失败那就根据undo log的sql进行回滚
\
优点:
1、不需要数据库支持XA协议,因为根据反向的sql进行回滚
2、在单机执行的时候就已经提交了,不需要等待全部提交后在提交,性能较快
\
\
3、基于事务补偿的 TCC
try: 资源预留 (hmily 是一种实现)
confirm:资源提交
cancel:资源回滚
TCC需要业务代码在每个分支上都写这三个函数,并且事务是TM发起的(TM是事务发起者,一般是某个服务),然后TM去调用每个分支事务的try方法,当try执行成功后,就进行confirm进行提交,如果失败了就cancel进行回滚
优点:
1、不需要依赖数据库,存靠业务逻辑来执行补偿
2、业务代码写的好的话,性能比较高
缺点:
1、代码量比较大,对开发者不友好
2、需要处理的场景多,悬挂、幂等等等
\
4、本地消息表
比如有个分布式事务AB,在执行一个分布式事务的时候,先执行A本地事务,并且往本地消息表写入一条中间状态,叫目前调用B中,然后在去执行B;然后约定当B执行完的时候,需要回调,把本地消息表的执行B改成执行完成;然后用一个线程去轮训本地消息表,如果出现正在执行B数据,表示调用失败,起码证明B还没回调; (B要处理幂等)
优点:
1、不需要借助太多开源组件和框架
2、该方法也比较好想到
缺点:
1、B需要实现幂等
2、整体流程还是比较复杂
\
5、事务消息 — 事务最终一致性(要求消费方一定要处理成功)
比如有分布式事务AB,执行本地消息的A的时候,通过事务消息确保把B发送出去,这个可以通过MQ的事务消息保证原子性,就是A执行成功了一定可以发出去,当A执行失败了,就删除B的消息,但是该消息消费是否成功看消费方,他只能保证消息一定发送出去
流程:
1、生产者往MQ发送half,预消息/半消息,此时消费者无法消费
2、生产者执行本地事务A
3、如果执行成功,那么提交之前的half消息,如果执行失败,那么删除half消息
4、为了防止3步骤的失败,消息队列会执行回查check函数(默认是1分钟),来看看是否需要提交还是回滚删除该消息
\
优点:
性能高,实现简单,只需要额外写一个回查函数
缺点:
分布式事务一致性只保证最终一致性,需要消费者来消费,就是要消费者无论如何也要消费成功,因为消息已经确定发出去了
\
6、最大努力通知 — 通过MQ的重试机制
一般用于通知对方
1、利用MQ的重试机制
2、提供回查接口,让别人主动查看事务状态