RocketMQ 源码分析 13 事务消息01

 executeLocalTransaction:方法,记录本地事务的事务状态,这里其实现就是循环设置事务消息的状态为0,1,2,demo中是把消息的状态数据存放在一个Map中,实际应用,应该会持久化消息的事务状态,例如数据库或缓存。
其关键是checkLocalTransaction,会查本地事务表,判断事务的状态如为0:UNKNOW,1:COMMIT_MESSAGE;ROLLBACK_MESSAGE。这里就能解释,生产者连续发10条消息,因为只有3条消息的事务状态为COMMIT_MESSAGE,故消息消费者只能消费3条。
   到这里,基本还是可以得知事务消息的实现方式,基本与文章开头所示的“网上声音”实现类似,下一节将详细分析TransactionMQProducer事务消息发送的实现细节。
在这里也可以提出一个疑问,如果事务消息的有PREPARED、COMMITED、ROLLBACK状态,RocketMQ如何快速找到PREPARED的消息,并去回查消息。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

事务消息实现原理01

 Step1:首先先阐述一下参数含义。final Message msg:消息;TransactionListener tranExecuter:事务监听器; Object arg:其他附加参数,该参数会再TransactionListener 回调函数中原值传入。

 Step2:在消息属性中,添加两个属性:TRAN_MSG,其值为true,表示为事务消息;PGROUP:消息所属发送者组,然后以同步方式发送消息。
   在消息发送之前,会先检查消息的属性TRAN_MSG,如果存在并且值为true,则通过设置消息系统标记的方式,设置消息为MessageSysFlag.TRANSACTION_PREPARED_TYPE
 Step3:Broker端首先客户发送消息请求后,判断消息类型,如果是事务消息,则调用TransactionalMessageService#prepareMessage方法,否则走原先的逻辑,调用MessageStore#putMessage方法

 step4:事务消息,将调用TransactionalMessageServiceImpl#prepareMessage方法,继而调用TransactionalMessageBridge#prepareMessage方法。

Step5:备份消息的原主题名称与原队列ID,然后取消是事务消息的消息标签,重新设置消息的主题为:RMQ_SYS_TRANS_HALF_TOPIC,队列ID固定为0。然后调用MessageStore#putMessage方法将消息持久化,这里TransactionalMessageBridge桥接类,就是封装事务消息的相关流程,最终调用MessageStore完成消息的持久化。消息入库后,会继续回到DefaultMQProducerImpl#sendMessageInTransaction,上文的Step2后面,也就是通过同步将消息发送到消息服务端。
  Step6:如果消息发送成功,会回调TransactionListener#executeLocalTransaction方法,执行本地事务,并且返回本地事务状态为:public enum LocalTransactionState {COMMIT_MESSAGE,ROLLBACK_MESSAGE,
UNKNOW,} 之一,注意:TransactionListener#executeLocalTransaction是在发送者成功发送PREPARED消息后,会执行本地事务方法,然后返回本地事务状态;如果PREPARED消息发送失败,则不会调用
TransactionListener#executeLocalTransaction,并且本地事务消息,设置为
LocalTransactionState.ROLLBACK_MESSAGE,表示消息需要被回滚。

step7:调用endTransaction方法结束事务(提交或回滚)

step8:组装结束事务请求,主要参数为:事务ID、事务操作(commitOrRollback)、消费组、消息队列偏移量、消息ID,fromTransactionCheck,从这里发出的请求,默认为false。Broker端的请求处理器为:EndTransactionProcessor。
   step9:EndTransactionProcessor根据事务提交类型:TRANSACTION_COMMIT_TYPE(提交事务)、TRANSACTION_ROLLBACK_TYPE(回滚事务)、TRANSACTION_NOT_TYPE、忽略该请求,会记录info级别的日志相关的代码将在下文详细分析,在这里,我们先大概梳理一条消息发送的路径TransactionMQProducer#sendMessageInTransaction的调用链来总结一下事务消息的发送流程。

  本文到这里,初步展示了事务消息的发送流程,总的说来,RocketMQ的事务消息发送使用二阶段提交思路,首先,在消息发送时,先发送消息类型为Prepread类型的消息,然后在将该消息成功存入到消息服务器后,会回调   TransactionListener#executeLocalTransaction,执行本地事务状态回调函数,然后根据该方法的返回值,结束事务
   1、COMMIT_MESSAGE :提交事务。
   2、ROLLBACK_MESSAGE:回滚事务。
   3、UNKNOW:未知事务状态,此时消息服务器(Broker)收到EndTransaction命令时,将不对这种消息做处理,消息还处于Prepared类型,存储在主题为:RMQ_SYS_TRANS_HALF_TOPIC的队列中,然后消息发送流程将结束,那这些消息如何提交或回滚呢?为了实现避免客户端需要再次发送提交、回滚命令,RocketMQ会采取定时任务将RMQ_SYS_TRANS_HALF_TOPIC中的消息取出,然后回到客户端,判断该消息是否需要提交或回滚,来完成事务消息的声明周期,该部分内容将在下节重点探讨。

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值