事务消息应用场景、实现原理与项目实战(附全部源码),SpringBoot集成Redis集群

其核心设计理念:

  • 应用程序开启一个数据库事务,进行数据库操作,并且在事务中发送一条PREPARE消息,PREPARE消息发送成功后通知应用程序记录本地事务状态,然后提交本地事务。

  • RocketMQ在收到类型为PREPARE的消息时,首先备份消息的原主题与原消息消费队列,然后将消息存储在主题为RMQ_SYS_TRANS_HALF_TOPIC的消息队列中,故PREPARE的消息是不会被客户端消费的。

  • Broker消息服务器开启一个定时任务处理RMQ_SYS_TRANS_HALF_TOPIC中的消息,会每隔指定时间向消息发送者发起事务状态查询请求 ,询问消息发送者客户端本地事务是否成功,然后根据回查状态决定是提交还是回滚,即对处于PREPARE状态进行提交或回滚操作。

  • 发送者如果明确得知事务成功,则可以返回COMMIT,服务端会提交该条消息,具体操作是恢复原消息的主题与队列,重新发送到Broker,消费端感知后消费。

  • 发送这如果无法明确得知事务状态,则返回UNOWN,此时服务端会等待一定时间后再次向发送者询问,默认询问15次。

  • 发送者如果非常明确得知事务失败,则可以返回ROLLBACK。

在具体实践中,消息发送者在无法获取事务状态时不要武断的返回ROLLBACK,而是要返回UNOWN,让服务端定时重试回查,说明如下:

在这里插入图片描述

在将PREPARE消息发送到Broker后,服务端发起事务查询时本地事务可能还未提交,为了避免无效的事务回查机制,RocketMQ通常至少在收到PREPARE消息6s后才会发起第一次事务回查,可通过 transactionTimeOut 配置。故客户端在实现事务回查时无法证明事务状态时不应该返回ROLLBACK,而是返回UNOWN。

3、事务消息实战


光说不练假把式,接下来以一个新用户注册送优惠券的场景来详细介绍如何使用事务消息。

项目模块职责说明如下:

在这里插入图片描述

事务消息的核心代码组装在transaction-service,其核心类图如下:

在这里插入图片描述

其中核心要点如下:

  • UserServiceImpl

Dubbo接口业务实现类,类似MVC的控制层,在这里做一些参数验证,但不执行具体的业务逻辑,只是发送一条事务消息到MQ。

  • UserRegTransactionListener

事务监听器,在 executeLocalTransaction 方法中执行业务逻辑,数据库本地事务加在该方法。

温馨提示:之所以不在UserServicveImpl中执行本地事务,是因为 executeLocalTransaction 中抛出的异常会被RocketMQ框架捕捉,及异常无法被UserServiceImpl感知,即无法实现其事务的一致性。

接下来展示其核心代码,如全部源码已上传到github仓库。

仓库

【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】

浏览器打开:qq.cn.hn/FTf 免费领取

地址:https://github.com/dingwpmz/rocketmq-learning

3.1 UserServiceImpl 核心实现

在这里插入图片描述

UserServiceImpl 的核心要点如下:

  • 首先应该对参数进行校验、业务逻辑进行校验,如果不满足业务条件,会发送一些无效消息到MQ,虽然不会造成业务异常,但会消耗性能

  • 发送事务消息,建议对消息设置Key,Key的值可以用业务处理流水号(可唯一表示该业务操作)或者核心业务字段(例如订单编号)

  • 业务入口类可通过事务消息发送状态来判断业务是否失败

3.2 UserRegTransactionListener 核心实现

事务监听器需要实现执行本地事务与事务回查两个接口。

3.2.1 实现 executeLocalTransaction

首先需要实现 executeLocalTransaction 方法,执行本地事务,其代码如下图所示:

在这里插入图片描述

其中几个关键点说明如下:

  • 在该方法上添加数据库事务标签。

  • 执行业务逻辑,示例Demo只是将用户数据存储到数据库。

  • 如果业务执行失败,可明确告知需要回滚,上层调用方也可根据ROLLBACK_MESSAGE进行相应的处理。

  • 如果业务成功,不建议直接返回COMMIT,而是建议返回UNKNOW,因为该方法尽管在方法最后一行,但可能发生断电等异常情况,数据库并没有成功。

3.2.2 实现 checkLocalTransaction

其次需要实现事务状态回查,用来RocketMQ服务端感知事务是否成功,其实现原理如下图所示:

在这里插入图片描述

其实现关键点如下:

  • 如果能明确得知本地事务成功,则返回COMMIT_MESSAGE

  • 如该不能明确得知本地事务成功,不能返回ROLLBACK_MESSAGE,而是返回UNKNOW,等待服务端下一次事务回查(不会立即触发),服务端默认回查15次,如果15次都得到UNKNOW,则会回滚该消息

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值