✅如何基于MQ实现分布式事务

典型回答

✅什么是分布式事务?

在分布式事务的实现中,有很多种方案,其中比较常用的就是基于MQ来实现,在MQ的具体实现中,又有很多种具体的方案,从大的方面来说可以分为两种:

  • 可靠消息最终一致性
  • 最大努力通知

可靠消息最终一致性

可靠消息最终一致性,顾名思义就是依赖可靠的消息,来实现一种最终一致性的模型。

他的大致流程就是:

1、事务的发起方执行本地事务

2、事务的发起方向事务的参与方发送MQ消息

3、事务的参与方接收到MQ消息后执行自己的本地事务

这里面事务的发起方和参与方都需要各自执行本地事务,他们之间,通过可靠消息来保障最终一致。

那么,怎么样的消息算可靠呢,直接依赖kafka、rocketMQ发送一个消息就可靠了么?显然是不行的,因为我们知道,在出现网络分区、网络延迟等情况时,是没办法保证消息一定可以发出去的,也没办法保证消息发出去就一定能被成功消费。

那么想要做到让这个消息可靠,一般由两种做法:

1、本地消息表

✅如何基于本地消息表实现分布式事务?

2、事务消息

✅RocketMQ的事务消息是如何实现的?

通过这两种方案,都可以保证事务的发起方在执行完本地事务之后,消息一定可以发出去,并且一定能被消费成功。

本地消息表的方案是基于本地事务+重试,来保证MQ消息一定可以发出去。

事务消息的方案是基于MQ的事务消息机制,把一条消息拆成两个half消息,通过2阶段的方式+回调反查来保证消息一定能发出去。

2者都是依赖MQ自身的重试机制+事务参与者反查+对账来保证消息一定可以消费。

最大努力通知

除了可靠消息最终一致性这种以外,还有一种方式就是也使用消息,但是这个消息并不要求一定可靠。这就是最大努力通知。

✅什么是最大努力通知?

这个方案一般就是只依赖重试机制,来做最大努力的通知事务参与者。但是需要注意的是,在最大努力通知的过程中,可能会出现消息重复发送的情况,也可能会出现消息丢失的情况。

扩展知识

三者区别

✅最大努力通知&事务消息&本地消息表三者区别是什么?

只用消息为啥不行

直接用MQ发消息为啥不可以呢,要搞本地消息表、事务消息等这么麻烦的方案呢?

主要有几个问题:

1、消息不可靠,不管是啥MQ,都没有办法保证100%的消息不丢的。所以,完全依赖消息是可能会丢消息的。

2、发消息和本地事务没办法保证一致性。我们在一个本地事务的操作和一个MQ发送操作,这俩保证不了一致性,有可能一个成功一个失败。比如,本地事务提交了,MQ发失败了。或者本地事务回滚了,MQ发成功了。都会导致最终的数据不一致。

本地事务提交了,MQ发失败了?

如果没有把MQ放到事务中,那么就会出现这种情况,导致MQ丢失。

本地事务回滚了,MQ发成功了?

当我们把MQ的发送也放到本地事务中的时候,一旦MQ发失败了,本地事务会回滚。但是问题是MQ有可能其实真正的是成功了,因为网络延迟等情况,他返回了失败,那这时候,就出现了不一致的情况。

原文: https://www.yuque.com/hollis666/xkm7k3/yuku2qztfb8ki6wg