消息队列是否需要事务呢?
这往往是必然的,用于解决生产者和消费者的数据一致性的问题
用户在电商APP上购物的时候,会先将商品加入购物车,然后下单,下单之后,购物车的商品往往需要删除,这个删除操作,往往是利用消息队列来异步的清理购物车的
在订单库中插入一条订单数据,创建订单
发消息给消息队列,消息的内容就是刚创建的订单
购物车订阅对应的主题,接收订单创建的消息,清理购物车,购物车中删除对应的商品
那么如果消费失败了,就会出现订单数据和购物车不一致的情况
所以引入了事务这个概念
那么消息队列如何实现分布式事务的呢?
Kafka和RocketMQ都提供了事务相关的功能
订单系统开启一个事务,然后订单系统给消息服务器发送一个半消息,这个半消息在事务提交之前,对消费者不可见
半消息发送之后,订单系统就执行本地事务了,订单库中创建一条订单记录,然后提交订单库的数据事务,然后根据本地成功来决定提交还是回滚半事务
对于半事务长时间没有提交半事务或者提交失败的话,Kafka和RocketMQ两个给出了不同的解决方案
Kafka直接抛出异常,用户自行处理
RocketMQ则有一个事务反查的机制,在提交或者回滚的时候,RocketMQ的Broker会定期的反查这个事务的本地事务状态,来根据结果提交或者回滚这个事务
为了支持这个事务反差的机制,我们需要实现一个反查本地事务的状态的接口,告知成功还是失败
而且这个反查,也不依赖于消息的发送方,无论哪个节点宕机了,还可以通过其他的订单服务的节点来反查,确保事务的完整性
流程基本如下
小结:
我们说明了事务的ACID特性
RocketMQ的事务反差机制,以及Kafka中没有这种反差机制