分布式事务

1、两阶段提交方案/XA方案

(1)阶段一
在这里插入图片描述
1)首先,事务协调者节点向所有的参与者节点发送Prepare请求。
2)接到Prepare请求后,每个参与者各自执行与事务有关的数据更新,写入Undo Log和Redo Log。如果执行成功,暂时不提交事务,而是向事务协调节点返回“完成”消息。如果执行不成功,向协调者返回失败。
3)当事务协调者接到了所有参与者的返回消息,则进入第二阶段。
(2)阶段二
1)如果在第一阶段,事务协调节点收到的都是正向返回,那么它将会向所有参与者发出Commit请求。
2)接到Commit请求后,参与者会各自进行本地事务提交,并释放锁资源。当完成提交后,将向事务协调者返回“完成”消息。
3)如果在第一阶段,事务协调节点有收到负向返回,那么协调节点向所有参与者发送Abort请求。
4)接收到Abort请求后,参与者节点需要在本地进行事务的回滚操作,回滚操作依照Undo Log来进行。

2、XA两阶段提交缺点

1)性能问题
遵循强一致性。在事务执行过程中,各个节点占用着数据库资源,只有当所有节点准备完毕,事务协调者才会通知提交,参与者提交后释放资源。
2)协调者单点故障问题
协调者节点挂掉,参与者会一直处于中间状态无法完成事务。
3)丢失消息导致的不一致问题。
如果网络问题,一部分事务参与者收到了提交消息,另一部分事务参与者没收到提交消息,就导致节点之间数据不一致。

3、TCC方案

举个例子,比如跨银行转账,如果用TCC方案来实现,是这样的:
1)Try阶段:先把两个银行账户中的资金给它冻结住就不让操作了
2)Confirm阶段:执行实际的转账操作,B银行账户的资金扣减,C银行账户的资金增加
3)Cancel阶段:如果任何一个银行的操作执行失败,那么就需要回滚进行补偿,就是比如B银行账户如果已经扣减了,但是C银行账户资金增加失败了,那么就得把B银行账户资金给加回去
在这里插入图片描述
这个用的少,除非是真的一致性要求太高,是系统中核心场景,比如资金类的场景,那可以用TCC方案了,自己编写大量的业务逻辑,自己判断一个事务中的各个环节是否ok,不ok就执行补偿/回滚代码。自己手写回滚逻辑、补偿逻辑,太恶心了,业务代码很难维护。

4、本地消息表

在这里插入图片描述
1)A系统在本地操作业务表
2)A系统将对应操作插入到消息表
3)A系统将这个消息发送到MQ中去
4)A系统对对应的消息注册一个监听
5)B系统接收到消息后,在一个事务里,先插入消息表,再操作业务表。如果该消息已经被处理,那么此时事务会回滚,保证不会重复处理。
6)B系统执行成功后,更新zk中的状态;如果处理失败了,就不会更新,A系统也就不会得到触发。
7)A系统定时扫描本地,如果有没处理的消息,会再次发送到MQ,让B再次处理
8)这个方案保证了最终一致性,哪怕B事务失败了,但是A会不断重发消息,直到B那边成功为止
缺点:
严重依赖于数据库的消息表,如果是高并发场景咋办呢?咋扩展呢?所以一般确实很少用。

5、可靠消息最终一致性方案

基于MQ来实现事务。RocketMQ就支持消息事务。
在这里插入图片描述
1)A系统发送一个prepared消息到mq,如果发送失败那么直接取消操作。(发送成功则说明mq是活着的)
2)如果这个消息发送成功过了,那么接着执行本地事务,如果成功就告诉mq发送确认消息,如果失败就告诉mq回滚消息
3)如果发送了确认消息,那么此时B系统会接收到确认消息,然后执行本地的事务
4)mq会自动定时轮询所有prepared消息回调你的接口,问你,这个消息是不是本地事务处理失败了,所有没发送确认消息?那是继续重试还是回滚?一般来说这里你就可以查下数据库看之前本地事务是否执行,如果回滚了,那么这里也回滚吧。这个就是避免可能本地事务执行成功了,别确认消息发送失败了。
5)这个方案里,要是系统B的事务失败了咋办?重试咯,自动不断重试直到成功,如果实在是不行,要么就是针对重要的资金类业务进行回滚,比如B系统本地回滚后,想办法通知系统A也回滚;或者是发送报警由人工来手工回滚和补偿。
这个还是比较合适的。

6、最大努力通知方案

在这里插入图片描述
1)系统A本地事务执行完之后,发送个消息到MQ
2)这里会有个专门消费MQ的最大努力通知服务,这个服务会消费MQ然后写入数据库中记录下来,或者是放入个内存队列也可以,接着调用系统B的接口
3)要是系统B执行成功就ok了;要是系统B执行失败了,那么最大努力通知服务就定时尝试重新调用系统B,反复N次,最后还是不行就放弃

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值