RocketMQ源码深入剖析(五)

RocketMQ源码深入剖析

9 分布式事务消息源码分析

9.1 什么是分布式事务?

业务场景:用户A转账100元给用户B,这个业务比较简单,具体的步骤:
1、用户A的账户先扣除100元
2、再把用户B的账户加100元

image.png

如果在同一个数据库中进行,事务可以保证这两步操作,要么同时成功,要么同时不成功。这样就保证了转账的数据一致性。
但是在微服务架构中,因为各个服务都是独立的模块,都是远程调用,都没法在同一个事务中,都会遇到分布式事务问题。

9.2 RocketMQ的解决方案

image.png

RocketMQ采用两阶段提交,把扣款业务和加钱业务异步化,在A系统扣款成功后,发送“扣款成功消息”到消息中间件;B系统中加钱业务订阅“扣款成功消息”,再对用户进行加钱。

9.2.1 解决方案的问题

在哪个阶段向RocketMQ发送消息?

1、先扣款后再向RocketMQ发消息

先扣款再发送消息,万一发送消息超时了(MQ中有可能成功,有可能失败),那这个状态就很难判断了

2、先向RocketMQ发消息后再扣款

扣款成功消息发送成功,但是如果本地扣款业务失败了,那消息已经发给MQ了,第二阶段的加钱就会执行成功。

所以我们发现,无论是哪种方案,处理起来都会有问题。

其实仔细分析下,问题的关键点,就是RocketMQ改变不了消息发送者的事务状态。所以RocketMQ的分布式事务方案进行了优化。

9.3 RocketMQ的分布式事务方案

image.png

所以RocketMQ在分布式事务中引入了半事务及事务回查机制。

半事务:
发一个消息到rocketmq,但该消息只储存在commitlog中,但consumeQueue中不可见,也就是消费端(订阅端)无法看到此消息。

事务回查:

RocketMq会定时遍历commitlog中的半事务消息,这个事务回查机制就可以站在 RocketMQ的角度参与消息发送者的事务中。

9.4 RocketMQ的分布式事务案例代码

image.png

这个是分布式事务的生产者,完成了半事务的发送。

通过事务回查,如果在TransactionListenerImpl类executeLocalTransaction方法中,如果本地事务执行成功,则提交commit_message,消费端即可消费消息

image.png

如果有一些比较耗时的操作导致,不能在这个步骤确认的话,可以提交UNKNOW,交给定时的任务回查来处理

image.png

image.png另外一点,如果担心生产者发生故障导致分布式事务的问题话,定时事务回查是可以在生产者群组中做的。

我们可以做一个这样的案例,一个生产者1,一个生产者2,消费发送时的分组是一样,都使用分布式事务消息。

生产者1发生故障了,消息状态还是一个UNKNOW状态,只要生产者2还存活,生产者2就可以帮助生产者1完成事务回查的确认,从而不会有单点故障问题。

image.png

image.png

image.png

image.png

image.png

image.png

image.png

9.5 分布式事务源码分析

从分布式事务的流程上,我们分析源码,可以从消息发送,确认/回滚 ,回查三个方面。

image.png

9.5.1 消息发送源码分析

Producer

image.png

image.png

image.png

Broker

RocketMQ使用Netty处理网络,broker收到消息写入的请求就会进入SendMessageProcessor类中processRequest方法。

最终进入DefaultMessageStore类中asyncPutMessage方法进行消息的存储

image.png

image.png

image.png

结合图同时结合代码,我们可以看到,在事务消息发送时,消息实际存储的主题是一个系统主题:RMQ_SYS_TRANS_HALF_TOPIC

同时消息中保存着消息的原有主题相关的信息与队列

image.png

9.5.2 确认/回滚源码分析

Producer

DefaultMQProducerImpl类sendMessageInTransaction方法

image.png

image.png

image.png

Broker

image.png

EndTransactionProcessor类

image.png

image.png

image.png

9.5.3 回查源码分析

Producer

事务回查中,Producer是服务端,所以需要注册服务处理

image.png

image.png

DefaultMQProducerImpl类checkTransactionState方法

image.png

image.png

DefaultMQProducerImpl类processTransactionState方法

image.png

image.png

image.png

image.png

Broker

在Broker启动的时候,是要作为客户端,定期的访问客户端做事务回查。

回顾到之前讲到《6.1 Broker启动流程分析》

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png事务回查是Broker发起的一次定时的网络调用(每隔60s),所以事务回查在客户端启动的时候第一次不一定是60s的间隔,一般会小于60s(因为事务回查是broker发起的,并不是client端定时发起)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值