1
、两阶段提交方案-XA
常见的场景:1个系统操作多个数据库 基于spring+JTA就可以搞定
但是不合法,一个系统跨多个库是不合法的。。。
2、TCC方案-三阶段
(写大量跟业务相关的代码 ,跟钱打交道的一般用,因为强一致),但是代码比较难维护
比如订单先插入一条流水,先查询库存服务,然后再调用库存扣减服务,再查询订单服务,如果符合库存,就认为成功,如果不符合,就调用库存回滚操作。
3、本地消息表(依赖与本地mysql表)
(1)A系统在自己本地操作业务同时,插入一条数据到消息表
(2)接着A系统将这个消息发送到MQ中去
(3)B系统在接收到消息之后,在一个是事务里 先往自己的本地消息表中插入一条数据,同时执行其他的业务,如果这个消息已经被处理过了,
那么此时这个事务会回滚,这样就保证不会重复处理消息
(4)B系统执行成功后,就会更新自己本地消息表的状态以及A系统消息表的状态(可以通过zk来监听某一个节点)
(5)如果B系统处理失败了,那么就不会通知更新A系统消息表状态,那么此时A此时就会不断重发消息,知道B成功为止。
4、可靠消息最终一致性方案
(1) A系统先发送一个prepare消息到mq,如果这个prepare消息发送失败就直接取消操作
(2)如果这个prepare消息发送成功了,那么接着执行本地事务,如果成功就告诉mq发送确认消息,如果失败就告诉mq回滚消息
(3)如果发送了确认消息 那么此时B系统会能接收到确认消息,然后执行本地事务
(4)mq会自动轮询所有prepared消息然后回调你的接口,问你这个消息是不是本地事务失败了,所以没发送确认消息?
那么是继续重试还是回滚?一般来说你可以在这个回调函数中查询下数据库看本地事务是否执行成功,如果成功,就可能是消息发送失败了,就重新发送消息就好了,如果本地事务就是失败了,那么就回滚mq中那条prepare就好了
(5)如果系统B失败了,就通知系统A不断重试,知道成功为止,,如果实在不行,那么就针对重要类业务进行回滚即可。。。
5、最大努力通知方案
有一个专门的通知服务,通过mq发送给这个通知您服务,然后在通知服务里去设置重试次数调用B系统即可。。。