两篇文章全面理解分布式事务问题(2) 柔性事务

56 篇文章 2 订阅

上一篇文章讲述的是抛弃A,保证CP的刚性分布式事务解决方案,这一篇介绍柔性分布式事务解决方案。

柔性事务遵循BASE理论,抛弃C,保证AP,以最终一致性来代替强一致性,柔性分布式事务解决方案中MQ承担非常重要的角色。

1.本地化消息表

A B两个分布式应用,各自有一个本地化消息表。

A中的业务和消息处于同一个本地事务中,也就意味着A的事务提交之后,消息表中也存放了这条消息。存完之后A系统会把这条消息发送到MQ.B接收到消息之后会写到本地消息表,同时执行业务逻辑.B应用也一样,业务和表处于同一个事务中。这里会有一个幂等操作,如果这条消息之前已经处理过,B就会回滚事务。B业务逻辑执行成功之后会更新消息的状态,同时更新A表的消息状态。

如果B系统处理失败了,那么就不会更新消息表状态,那么此时A系统会定时扫描自己的消息表,如果有没处理的消息,会再次发送到MQ中去,让B再次处理

这个方案保证了最终一致性,哪怕B事务失败了,但是A会不断重发消息,直到B那边成功为止

2.基于支持事务的MQ

上述方法有个比较不好地方,就是需要各个应用在本地建一个表,和业务耦合度比较高。有没有不需要本地建表的方法呢?

市面上有一些MQ支持事务的,比如RocketMQ。

在介绍这种方法之前先解释一下RocketMQ的几个名词

prepare消息    又名Half Message,半消息,标识该消息处于"暂时不能投递"状态,不会被Comsumer所消费,待服务端收到生成者对该消息的commit或者rollback响应后,消息会被正常投递或者回滚(丢弃)消息
RMQ_SYS_TRANS_HALF_TOPIC    prepare消息在被投递到Mq服务器后,会存储于Topic为RMQ_SYS_TRANS_HALF_TOPIC的消费队列中
RMQ_SYS_TRANS_OP_HALF_TOPIC    在prepare消息被commit或者rollback处理后,会存储到Topic为RMQ_SYS_TRANS_OP_HALF_TOPIC的队列中,标识prepare消息已被处理
 

第一阶段:生产者向MQ服务器发送事务消息(prepare消息),服务端确认后回调通知生产者执行本地事务(此时消息为Prepare消息,存储于RMQ_SYS_TRANS_HALF_TOPIC队列中,不会被消费者消费)

第二阶段:生产者执行完本地事务后(业务执行完成,同时将消息唯一标记,如transactionId与该业务执行记录同时入库,方便事务回查),根据本地事务执行结果,返回Commit/Rollback/Unknow状态码

1、服务端若收到Commit状态码,则将prepare消息变为提交(正常消息,可被消费者消费)
2、收到Rollback则对消息进行回滚(丢弃消息)
3、若状态为Unknow,则等待MQ服务端定时发起消息状态回查,超过一定重试次数或者超时,消息会被丢弃

事务状态定时回查
在第二阶段中,生产者在本地事务执行完成后,需要向MQ服务器返回响应状态码,发送状态码的过程也是通过Netty发送网络请求,假设由于网络原因发送失败怎么办?本地事务已经提交/回滚了,但是Commit/Rollback状态码却没发出去,那么MQ服务器上这条prepare消息状态岂不是无法被投递/回滚

因此,MQ服务端会定时扫描存储于RMQ_SYS_TRANS_HALF_TOPIC中的消息,若消息未被处理,则向消费发送者发起回调检查,检查消息对应本地事务执行状态。从而保证消息事务状态最终能和本地事务的状态一致。上图中的4、5、6就是MQ服务端定时回查步骤。
如果B系统消费消息之后执行业务逻辑失败怎么办,没问题,MQ会一直重试。

这个方法比较好的地方在于把消息和业务系统独立开,符合分布式应用的特点。唯一的缺点就是市面上支持事务的MQ比较少。

3.最大努力通知方案

1、系统 A 本地事务执行完之后,发送个消息到 MQ;

2、这里会有个专门消费 MQ 的最大努力通知服务,这个服务会消费 MQ 然后写入数据库中记录下来,或者是放入个内存队列也可以,接着调用系统 B 的接口;

3、要是系统 B 执行成功就 ok 了;要是系统 B 执行失败了,那么最大努力通知服务就定时尝试重新调用系统 B,反复 N 次,最后还是不行就放弃。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值