分布式事务TCC具体方案和RocketMQ机制

分布式事务TCC实现思路

A

    B{远程方法成功

     c{本地方法失败, 如何回滚远程方法B的操作

 

这里涉及到两个系统的事务,我们来用Redis 设计一套TCC回滚方案。

 

@自定义分布式事务注解(ID=null

@Transactional

A{  

      创建唯一标识也好,假设20190503   ,并动态修改注解内的值ID= 20190503

    ---执行其他业务逻辑

方法B开始往redis 写入预写日志:

接着调用方法B);

方法B结束 往redis 写入写结束日志:

   ---执行其他业务逻辑

  

 

  B开始写入

  Key=20190503 ,value=[

{"统一事务ID”: "20190503",“方法标识”:“ beanName.类名.方法名B”,“事务开始标识”:“1”,“事务结束标识”:“0 , “参数”:“Object”}]

 

 B成功后修改

Key=20190503 ,value=[

{"统一事务ID”: "20190503",“方法标识”:“ beanName.类名.方法名B”,“事务开始标识”:“1”,“事务结束标识”:“1 , “参数”:“Object”}]

 

如果出现B成功,A最后失败了,结果就是

  A 失败的结果就没来的及修改事务结束标识,结果就是如下

  Key=20190503 ,value=[

{"统一事务ID”: "20190503",“方法标识”:“ beanName.类名.方法名B”,“事务开始标识”:“1”,“事务结束标识”:“0 , “参数”:“Object”}]

 

接下来就是失败回滚逻辑

写一个对@自定义分布式事务注解(ID=null的AOP 切面,在这里做异常捕抓,

通过注解中的ID 获取Redis 中的

Key=20190503 ,value=[

{"统一事务ID”: "20190503",“方法标识”:“ beanName.类名.方法名B”,“事务开始标识”:“1”,“事务结束标识”:“1”, “参数”:“Object”}]

    这个时候找到这个list中“事务结束标识”:“1”中的对象,通过反射加spring容器中加载对对应的bean来执行,  类名.方法名B Cancel(Object)方法,这个方法执行回滚逻辑,具体实现由程序员实现。

具体执行代码如下:

Object beanObject = SpringContextHolder.getBean("beanName");只能从容器中获取,不能用反射获取对象,因为是代理接口。
                Class<?> clazz = Class.forName("类全名");
                // 获取本类的所有方法,存放入数组
                Method[] methods = clazz.getDeclaredMethods();
                for (Method method : methods) {
                    if (method.getName().equals("方法名"+“Cancel”)) {
                        Object resul = method.invoke(beanObject,"参数");
                    }
                }

   已测可行。

  要是B操作是一个更新操作或者删除操作,只需要更新之前将可以从数据库中加载这条数据出来缓存到Redis几秒钟即可,xxxCancel(),  知道了之前的数据是怎么样的就可以更新了。 

 

现实中我们有另外一种场景,就是本地方法A执行完了发送消息,让消费者B执行另外一个远程服务,阿里给出的解决方案是

用RocketMQ 来保证 A本地事务和发送消息的一致性,不保证A和B的一致性,换句话就是  它能保证  A成功了消息也一定成功,B能不能成功消费它就不保证了,如果A成功,B失败了,你只能人工解决了,记录日志,发送通知啥的,自行脑补。

它的大概原理是这样的:

方法A开始执行, 发送Prepared消息,可以理解为发送了一个状态为0 的消息,这时消费者是不会消费这条消息的。

接着执行方法A的其他逻辑,执行完了再次发送状态为1的确认消息。这个时候消费者可以消费这条消息了。

如果这条状态为1的消息发送失败,或者根本没就运行到这里A就出异常了,那么mq服务会按一分钟检测一次,发现状态为0 的消息后,向生产者询问,如果没人回答,则mq认为这条消息无效,如果回答OK,则mq会修改这条消息的状态为1.大概就是这样一个原理。接下来就是B能不能消费的问题了,如果是网络问题就重试,反正B能不能成功无法保证。

要保证回滚A太复杂了,得不偿失,这是阿里给的答案,人工处理。

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值