当前位置: 首页 > news >正文

Spring Boot: 使用 @Transactional 和 TransactionSynchronization 在事务提交后发送消息到 MQ

Spring Boot: 使用 @TransactionalTransactionSynchronization 在事务提交后发送消息到 MQ

在微服务架构中,确保消息的可靠性和一致性非常重要,尤其是在涉及到分布式事务的场景中。本文将演示如何使用 Spring Boot 的事务机制和 TransactionSynchronization 来在事务提交后发送消息到消息队列(MQ)。这样可以保证只有在事务成功提交后,消息才会被发送。

背景

在处理数据更新的同时,我们可能需要将一些数据变更的消息推送到消息队列(例如 RabbitMQ、Kafka)。为了保证数据和消息的一致性,通常需要在事务提交后再发送消息。Spring 的 @Transactional 注解和 TransactionSynchronization 机制非常适合处理这种需求。

我们将通过一个简单的示例,演示如何在事务提交后发送消息。我们将使用 RabbitMQ 作为消息队列,但这个方法可以扩展到其他类型的 MQ。

核心思想

  • 事务同步: 使用 TransactionSynchronizationManager 注册一个事务同步回调,确保消息在事务提交后被发送。
  • afterCommit 回调: 该回调将在事务成功提交后执行,确保只有在数据操作成功时才会发送消息。

步骤概述

  1. 定义一个服务: 使用 @Transactional 注解来确保数据操作在事务中进行。
  2. 注册事务同步回调: 在事务内注册一个同步回调,确保在事务提交后发送消息。
  3. 消息发送: 使用 RabbitTemplate 将消息发送到 RabbitMQ 或其他消息队列。

示例:使用 TransactionSynchronization 在事务提交后发送消息

1. 配置 RabbitMQ

首先,我们需要配置 RabbitMQ 的连接。我们将使用 Spring Boot 提供的 RabbitTemplate 来发送消息。

@Configuration
public class RabbitConfig {@Beanpublic Queue orderQueue() {return new Queue("orderQueue", false);}@Beanpublic RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {return new RabbitTemplate(connectionFactory);}
}
2. 定义业务服务

接下来,我们创建一个业务服务 MyService,它将在事务提交后发送消息到消息队列。在该服务中,我们使用 @Transactional 来管理事务,并通过 TransactionSynchronizationManager.registerSynchronization 注册一个事务同步回调,确保在事务提交成功后才发送消息。

@Service
public class MyService {@Autowiredprivate RabbitTemplate rabbitTemplate;@Transactionalpublic void doSomething() {// 执行一些业务逻辑,例如保存数据库记录System.out.println("Executing business logic...");// 注册事务同步回调TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {@Overridepublic void afterCommit() {// 事务提交后发送 MQ 消息rabbitTemplate.convertAndSend("exchangeName", "routingKey", "Message after commit");System.out.println("Message sent after commit!");}@Overridepublic void beforeCompletion() {// 可选:在事务完成前做一些操作}});}
}
3. 处理事务和消息

doSomething() 方法中,我们进行了数据库操作(模拟的业务逻辑),并注册了一个事务同步回调。这个回调会在事务提交成功后执行,发送一条消息到 RabbitMQ。消息的发送是在事务提交后进行的,因此我们确保了消息与数据的操作一致性。

  • 事务提交后才发送消息: 只有在事务提交成功后,afterCommit 方法中的消息发送操作才会被执行。
  • 失败回滚: 如果事务执行失败,消息不会被发送,因为事务会回滚,afterCommit 方法不会被调用。
4. 控制事务提交和回滚

你可以在业务逻辑中使用 @Transactional 注解来管理事务。当事务提交时,注册的同步回调将被触发,从而发送消息。示例如下:

@RestController
@RequestMapping("/orders")
public class OrderController {@Autowiredprivate MyService myService;@PostMapping("/create")public ResponseEntity<String> createOrder(@RequestBody Order order) {try {myService.doSomething();return ResponseEntity.ok("Order processed successfully");} catch (Exception e) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Order processing failed");}}
}

扩展:多个事务提交,多个不同消息的例子

假设我们需要在一个方法中处理多个不同类型的事务,并根据不同的条件发送不同的消息。我们可以扩展上述示例,实现多个事务和不同消息发送。

@Service
public class MyService {@Autowiredprivate RabbitTemplate rabbitTemplate;@Transactionalpublic void doSomethingMultipleOrders(Order order1, Order order2) {// 处理订单1System.out.println("Processing order 1...");// 注册事务同步回调,发送订单1的消息TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {@Overridepublic void afterCommit() {rabbitTemplate.convertAndSend("exchangeName", "routingKey1", "Order 1 message after commit");System.out.println("Order 1 message sent after commit!");}});// 处理订单2System.out.println("Processing order 2...");// 注册事务同步回调,发送订单2的消息TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {@Overridepublic void afterCommit() {rabbitTemplate.convertAndSend("exchangeName", "routingKey2", "Order 2 message after commit");System.out.println("Order 2 message sent after commit!");}});}
}

在上面的代码中,我们为两个订单分别注册了事务同步回调。每个回调在事务提交后发送不同的消息。这可以扩展为多个事务提交,针对每个不同的事务执行不同的消息发送操作。

总结

通过使用 Spring 的 @Transactional 注解和 TransactionSynchronizationManager,我们可以确保只有在事务提交后才会发送消息。这个方法可以用于各种 MQ 实现(如 RabbitMQ、Kafka),并且能保证事务和消息的顺序一致性。在实际应用中,这种方法可以帮助我们有效避免消息丢失和数据不一致的问题。

希望本篇博客能够帮助你理解如何在 Spring Boot 中使用事务机制来确保在事务提交后发送消息,并且能够处理多个事务和多个消息的情况。

相关文章:

Spring Boot: 使用 @Transactional 和 TransactionSynchronization 在事务提交后发送消息到 MQ

Spring Boot: 使用 Transactional 和 TransactionSynchronization 在事务提交后发送消息到 MQ 在微服务架构中&#xff0c;确保消息的可靠性和一致性非常重要&#xff0c;尤其是在涉及到分布式事务的场景中。本文将演示如何使用 Spring Boot 的事务机制和 TransactionSynchron…...

LQB(2)-python-枚举

前言 python中的枚举一般有两个说法&#xff0c;一个是枚举算法&#xff08;暴力求解法&#xff0c;算法层面&#xff09;&#xff0c;一个是遍历使用enumerate()函数或者enum模块创建&#xff08;&#xff09;。 暴力求解法在之前的博文里面讲过了&#x1f447;&#xff0c;…...

MongoDB开发规范

分级名称定义P0核心系统需7*24不间断运行&#xff0c;一旦发生不可用&#xff0c;会直接影响核心业务的连续性&#xff0c;或影响公司名誉、品牌、集团战略、营销计划等&#xff0c;可能会造成P0-P2级事故发生。P1次核心系统这些系统降级或不可用&#xff0c;会间接影响用户使用…...

为什么DeepSeek服务器繁忙?

致敬DeepSeek 用户层面 用户数量激增&#xff1a;DeepSeek 免费且功能强大&#xff0c;对普通用户和开发者都极具吸引力124。尤其是在新功能推出、新模型上线或相关热门活动期间&#xff0c;大量用户会在短时间内涌入9。例如春节期间&#xff0c;DeepSeek 的用户量达到四千万7。…...

律所录音证据归集工具:基于PyQt6与多线程的自动化音频管理解决方案

在律所日常工作中&#xff0c;音频证据的整理与归集是一个高频且复杂的任务。面对大量的案件录音文件&#xff0c;如何实现快速且准确的分类与存档&#xff0c;成为了律所提高效率、降低出错率的关键。本文将通过技术角度解析一款名为律所录音证据归集工具的项目&#xff0c;详…...

【含开题报告+文档+PPT+源码】基于SpringBoot+Vue旅游管理网站

开题报告 本论文探讨了一款采用现代Web开发技术构建的台州市旅游综合信息与服务平台的设计与实现。该系统基于SpringBoot框架&#xff0c;以其轻量级、快速开发和强大的企业级应用支持能力为核心后端技术支撑&#xff0c;结合Vue.js前端框架及ElementUI组件库&#xff0c;为用…...

unity碰撞的监测和监听

1.创建一个地面 2.去资源商店下载一个火焰素材 3.把procedural fire导入到自己的项目包管理器中 4.给magic fire 0 挂在碰撞组件Rigidbody , Sphere Collider 5.创建脚本test 并挂在magic fire 0 脚本代码 using System.Collections; using System.Collections.Generic; usi…...

DeepSeek-R1 32B Windows+docker本地部署

最近国产大模型DeepSeek兴起&#xff0c;本地部署了一套deepseek同时集成Open WebUI界面,给大家出一期教程。 软件&#xff1a;Ollama、docker、Open WebUI 一、用Ollama下载模型 首先我们需要安装Ollama&#xff0c;它可以在本地运行和管理大模型。 到Ollama官网 https://ol…...

C++11新特性之unique_ptr智能指针

本节继续介绍智能指针&#xff0c;不了解的读者可以先阅读——C11新特性之shared_ptr智能指针-CSDN博客 1.介绍 unique_ptr是C11标准提供的另一种智能指针。与shared_ptr不同的是&#xff0c;unique_ptr指针指向的堆内存无法同其他unique_ptr共享&#xff0c;也就是每一片堆内…...

Vue与Konva:解锁Canvas绘图的无限可能

前言 在现代Web开发中&#xff0c;动态、交互式的图形界面已成为提升用户体验的关键要素。Vue.js&#xff0c;作为一款轻量级且高效的前端框架&#xff0c;凭借其响应式数据绑定和组件化开发模式&#xff0c;赢得了众多开发者的青睐。而当Vue.js邂逅Konva.js&#xff0c;两者结…...

python绘图之柱状堆积图的绘制

本节来学习用python来绘制柱状堆积图. 使用的库为matplotlib.pyplot,numpy 代码如下 # 导入必要的库 import matplotlib.pyplot as plt # 用于绘图 import numpy as np # 用于数值计算# 模拟一些数据 x [数值{}.format(i) for i in range(10)] # 创建一个包含10个元素的列…...

剪辑学习整理

文章目录 1. 剪辑介绍 1. 剪辑介绍 剪辑可以干什么&#xff1f;剪辑分为哪些种类&#xff1f; https://www.bilibili.com/video/BV15r421p7aF/?spm_id_from333.337.search-card.all.click&vd_source5534adbd427e3b01c725714cd93961af 学完剪辑之后如何找工作or兼职&#…...

DeepSeek从入门到精通:全面掌握AI大模型的核心能力

文章目录 一、DeepSeek是什么&#xff1f;性能对齐OpenAI-o1正式版 二、Deepseek可以做什么&#xff1f;能力图谱文本生成自然语言理解与分析编程与代码相关常规绘图 三、如何使用DeepSeek&#xff1f;四、DeepSeek从入门到精通推理模型推理大模型非推理大模型 快思慢想&#x…...

AI大模型训练实战:分布式与微调指南

AI大模型训练实战:分布式与微调指南 适用人群:有一定深度学习基础,正在或即将参与大模型(如 GPT、DeepSeek 等)训练与部署的工程师、研究者;想要理解分布式策略与微调方法的读者。 一、大模型为何需要分布式与微调? 随着 GPT、DeepSeek 等大模型参数规模攀升至数十亿甚…...

整合 Redis 分布式锁:从数据结构到缓存问题解决方案

引言 在现代分布式系统中&#xff0c;Redis 作为高性能的键值存储系统&#xff0c;广泛应用于缓存、消息队列、实时计数器等多种场景。然而&#xff0c;在高并发和分布式环境下&#xff0c;如何有效地管理和控制资源访问成为一个关键问题。Redis 分布式锁正是为了解决这一问题…...

并查集题目

并查集题目 聚合一块&#xff08;蓝桥&#xff09;合根植物&#xff08;蓝桥&#xff09;等式方程的可满足性省份数量 并查集&#xff08;Union-Find&#xff09;算法是一个专门针对「动态连通性」的算法。双方向的连通。 模板&#xff1a; class UF {// 连通分量个数private …...

日志2025.2.9

日志2025.2.9 1.增加了敌人挥砍类型 2.增加了敌人的死亡状态 在敌人身上添加Ragdoll&#xff0c;死后激活布偶模式 public class EnemyRagdoll : MonoBehaviour { private Rigidbody[] rigidbodies; private Collider[] colliders; private void Awake() { rigidbodi…...

支持多种网络数据库格式的自动化转换工具——VisualXML

一、VisualXML软件介绍 对于DBC、ARXML……文件的编辑、修改等繁琐操作&#xff0c;WINDHILL风丘科技开发的总线设计工具——VisualXML&#xff0c;可轻松解决这一问题&#xff0c;提升工作效率。 VisualXML是一个强大且基于Excel表格生成多种网络数据库文件的转换工具&#…...

Java并发编程笔记

Java并发基础知识补全 启动 启动线程的方式只有&#xff1a; 1、X extends Thread;&#xff0c;然后X.start 2、X implements Runnable&#xff1b;然后交给Thread运行 线程的状态 Java中线程的状态分为6种&#xff1a; 1. 初始(NEW)&#xff1a;新创建了一个线程对象&…...

大语言模型实践——基于现有API的二次开发

基于现有的API平台做一些实用的AI小应用。 API服务商&#xff1a;阿里云百炼 云服务器&#xff1a;阿里云&#xff08;2核2GB&#xff09; 部署框架&#xff1a;gradio 调用框架&#xff1a;openai 语言&#xff1a;Python &#xff08;注&#xff1a;若搭建网站或API接口…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...