rocketmq事务消息入门介绍

引出分布式事务相关内容面试

这里主要是想说明下,是什么背景下面产生了此类问题。redis

首先咱们来讲说事务,说道事务,首先让我想到的就是我大学的时候,老师常常举例转帐的事情,例子是这样的:spring

银行转帐!张三转100块到李四的帐户,这其实须要两条SQL语句:
  • 给张三的帐户减去100元
  • 给李四的帐户加上100元
若是在第一条SQL语句执行成功后,在执行第二条SQL语句以前,程序被中断了(多是抛出了某个异常,也多是其余什么缘由),那么李四的帐户没有加上100元,而张三却减去了100元。这确定是不行的!你如今可能已经知道什么是事务了吧!事务中的多个操做,要么彻底成功,要么彻底失败!不可能存在成功一半的状况!也就是说给张三的帐户减去100元若是成功了,那么给李四的帐户加上100元的操做也必须是成功的;不然给张三减去100元,以及给李四加上100元都是失败的!

若是在单个服务里面,咱们使用spring的话,咱们使用一个注解就解决了这个问题(@Transactional注解就解决了,基本上就没有下文什么事情了。)数据库

随着各各公司服务愈来愈复杂,数据量愈来愈多,慢慢的公司就引入了微服务以及分库分表等技术,这些技术的确很是的有用,可是在解决事务方面带来了一下问题。apache

强调下:分布式事务,咱们通常都是强调的最终一致性,而不是强一致性!!!网络

主要归纳为3类:架构

  • 基于单个JVM,数据库分库分表了(跨多个数据库)。
  • 基于多JVM,服务拆分了(不跨数据库)。
  • 基于多JVM,服务拆分了 而且数据库分库分表了。

正是为了解决上面的3类问题,才引入了分布式事务相关的技术来解决这些问题。分布式

Half(Prepare) Message微服务

指的是暂不能投递的消息,发送方已经将消息成功发送到了 MQ 服务端,可是服务端未收到生产者对该消息的二次确认,此时该消息被标记成“暂不能投递”状态,处于该种状态下的消息即半消息。学习

消息回查

因为网络闪断、生产者应用重启等缘由,致使某条事务消息的二次确认丢失,MQ 服务端经过扫描发现某条消息长期处于“半消息”时,须要主动向消息生产者询问该消息的最终状态(Commit 或是 Rollback),该过程即消息回查。

执行流程图

 

 

 

 

 

  1. 发送方向 MQ 服务端发送消息。
  2. MQ Server 将消息持久化成功以后,向发送方 ACK 确认消息已经发送成功,此时消息为半消息。
  3. 发送方开始执行本地事务逻辑。
  4. 发送方根据本地事务执行结果向 MQ Server 提交二次确认(Commit 或是 Rollback),MQ Server 收到 Commit 状态则将半消息标记为可投递,订阅方最终将收到该消息;MQ Server 收到 Rollback 状态则删除半消息,订阅方将不会接受该消息。
  5. 在断网或者是应用重启的特殊状况下,上述步骤4提交的二次确认最终未到达 MQ Server,通过固定时间后 MQ Server 将对该消息发起消息回查。
  6. 发送方收到消息回查后,须要检查对应消息的本地事务执行的最终结果。
  7. 发送方根据检查获得的本地事务的最终状态再次提交二次确认,MQ Server 仍按照步骤4对半消息进行操做。

事务消息发送对应步骤一、二、三、4,事务消息回查对应步骤五、六、7。

RocketMQ事务消息如何使用

一、引入 rocketmq-client

 

 

 

 

目前尚未,等几天就会有了,或者本身下载源码进行打包到本身的私有仓库也是同样的,通过和4.2.0的引入差很少,就是换成4.3.0便可。

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-client</artifactId>
    <version>4.3.0</version>
</dependency>

二、编写Producer

 

 

 

 

备注:和普通消息发送 DefaultMQProducer有所不一样,这里使用的是 TransactionMQProducer

 

 

 

 

 

关键点: 本身实现TransactionListener接口,并实现 executeLocalTransaction方法(执行本地事务的,通常就是操做DB相关内容)和 checkLocalTransaction方法(用来提供给broker进行会查本地事务消息的,把本地事务执行的结果存储到redis或者DB中均可以,为会查作数据准备)。

仍是以:给张三的帐户减去100元, 给李四的帐户加上100元为例。这个时候咱们发送就至关于作的是张三的帐户减去100元的操做,而且操做DB成功了,下面就是另外对李四的帐户加上100元的操做了,这个时候就是至关于定义刚刚发送事务消息的topic,消费端和咱们普通的消费端没有什么区别。

思考:假如这个时候咱们消费端失败了怎么办呢?(这个问题后续有讨论,消费失败有2种,第一种是超时了,咱们重试便可,第二种是真的处理失败了?该怎么办呢?)

RocketMQ事务消息是怎么实现的

第一感受和定时消息作法很是相似,可是比定时消息要复杂。定时消息内容在:RocketMQ(九):消息发送(续)里面提到过。

本质: 定时消息先把定时消息的topic修改成SCHEDULE_TOPIC_XXXX,以后一系列处理……,咱们这个事务消息也是同样,先发送Half(Prepare) Message消息的时候,其实topic内容也继续了修改(RMQ_SYS_TRANS_HALF_TOPIC),全部consumer是不可见的(若是提交就用真实topic,若是须要回滚那么就那临时的topic内容删除便可。)

Half(Prepare) Message修改topic断点以下:

 

 

 

 

本篇仅仅是一个入门介绍,里面具体细节后续章节会进行分析。

思考: 若是把发送普通消息和本地执行逻辑放在一个事务里面,若是执行事务成功就发送普通消息,若是失败就回滚好像也是能够,那么这种事务消息相对其有什么优点或者好处呢??? 思考下。

为何须要事务消息会查机制

其实这个内容在,RocketMQ事务消息介绍里面也说明了,因为网络闪断、生产者应用重启等缘由,致使某条事务消息的二次确认丢失,MQ 服务端经过扫描发现某条消息长期处于“半消息”时,须要主动向消息生产者询问该消息的最终状态(Commit 或是 Rollback),该过程即消息回查。那么RocketMQ到底怎么作的呢?下面立刻就会介绍。

RocketMQ是怎么进行事务消息会查的

每60s会对Half(Prepare) Message的topic主题为RMQ_SYS_TRANS_HALF_TOPIC的消息进行check。

 

 

 

 

 

 

 

 

broker会调用本身实现TransactionListener接口的checkLocalTransaction方法

 

 

 

 

备注: 就是RocketMQ已经实现这个机制,今天这篇仅仅是入门介绍,并无涉及到不少细节,先把大概流程说明白,后续再具体细节进行开篇说明。

RocketMQ对于分布式事务解决还有那些局限性?以及说明

在RocketMQ事务消息如何使用的时候咱们提到,若是消费失败怎么办?消费失败有2种,第一种是超时了,咱们重试便可,第二种是真的处理失败了?仔细思考下,这块仍是蛮复杂的,假如须要有7-8个业务模块呢,其中执行到第6个业务模块就失败呢? 这种重试好几回仍是失败,咱们该如何处理呢???是回滚前面5个操做吗?好复杂好复杂,为何RocketMQ不提供自动回滚呢? 但愿你们思考下,若是失败率比较大,那么就是系统问题须要优化代码业务……

据零度了解,不少这块是经过人工介入以及T+1对帐的以及补偿机制等。

欢迎工做一到五年的Java工程师朋友们加入Java架构开发:点击连接加入群聊【Java架构交流群】:https://jq.qq.com/?_wv=1027&k=5DmXtYD

本群提供免费的学习指导 架构资料 以及免费的解答

不懂得问题均可以在本群提出来 以后还会有职业生涯规划以及面试指导

同时你们能够多多关注一下小编 你们一块儿学习进步

相关文章
相关标签/搜索