rocketmq事务消息原理?
RocketMQ的事务消息主要由三部分组成:半消息(Half Message)、执行本地事务和事务补偿机制。下面详细介绍这三部分:
- 半消息(Half Message)用户向RocketMQ发送半消息,这是一个预处理消息,也就是说它不会被消费者所消费。半消息主要存储在Commit Log中。
- 执行本地事务在用户的业务服务中执行本地事务。本地事务的执行结果可能成功或失败,根据本地事务的执行结果,用户会向RocketMQ提交事务或者回滚事务。
- 提交或回滚消息如果本地事务执行成功,用户会向RocketMQ提交事务,这将会使得之前的半消息变为可消费的消息;如果本地事务执行失败,那么用户可以回滚事务,这将会删除之前存储的半消息。
- 事务补偿机制如果在上述过程中产生了某些故障,例如网络问题或者应用崩溃导致RocketMQ没有收到事务提交或回滚指令,RocketMQ提供了一种事务检查机制。RocketMQ会定期扫描哪些处于"半消息"状态的消息,然后询问用户这些消息对应的本地事务执行结果。然后根据用户的反馈决定是提交还是回滚。
注:回查请求内容: CHECK_TRANSACTION_STATE 请求码
"CHECK_TRANSACTION_STATE":这是一种命令类型,表示需要检查事务状态。
"producerGroup":生产者所在的组。
"tranStateTableOffset":事务状态表中的偏移值。
"commitLogOffset":提交日志中的偏移值。
"msgId":消息ID。
RocketMQ在事务消息的处理过程中,Broker和生产者端使用了特定的请求码进行通信。
请求码: Broker向生产者发送回查事务状态的请求时,会通过"CHECK_TRANSACTION_STATE"请求码来标识该操作。
当生产者客户端收到这个请求码后,它会进一步执行以下操作:
- RocketMQ客户端对每个生产者实例注册一个TransactionListener,这个监听器包含两个方法:executeLocalTransaction 和 checkLocalTransaction。前者用于执行本地事务,后者用于检查本地事务的状态。
- 当生产者客户端收到"CHECK_TRANSACTION_STATE"请求时,然后找到生产组,客户端会将生产组缓存起来,找到 MQProducerInner producer = this.mqClientFactory.selectProducer(group);,然后调用对应的producer中的TransactionListener中的checkLocalTransaction方法。
- checkLocalTransaction方法会根据业务逻辑判断事务执行结果,并返回一个枚举值:COMMIT_MESSAGE、ROLLBACK_MESSAGE或者UNKNOW。COMMIT_MESSAGE表示事务提交,ROLLBACK_MESSAGE表示事务回滚,UNKNOW表示未知状态。
- 客户端将这个结果响应给Broker,Broker根据响应结果更新消息的状态。
通过以上的步骤,RocketMQ可以确保消息的发送和本地事务的执行具有原子性,即要么都成功,要么都失败。
此外,RocketMQ内部通过一个CheckTransactionStateService服务线程来定期扫描消息,判断其是否需要检查。RocketMQ不会对每一条消息进行事务状态检查,只有当一条消息第一次被发出并且已经等待了一段时间(默认超过6s),RocketMQ才会触发事务状态的检查。
对于消息的发送方来说,如果收到RocketMQ的事务状态回查请求,需要重新检查本地事务的执行状态,然后再次向RocketMQ确认消息提交或回滚。