常见几种分布式事物解决方案

163 阅读4分钟

分布式事物:

\

2PC(基于数据库XA和阿里的Seata)、3PC、TCC、本地消息表、MQ事务消息等

\

1、基于XA的两阶段提交

TM发送多个sql到数据库上,此时不提交,如果多个都执行成功了,就统一commit,否则就rollback

缺点:

1、需要数据库支持XA协议

2、性能比较慢,因为需要全部执行成功了才commit

3、commit可能会丢失

Pasted Graphic 1.tiff

\

\

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、需要处理的场景多,悬挂、幂等等等

Pasted Graphic 2.tiff

\

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、提供回查接口,让别人主动查看事务状态