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

解决Spring事务中RPC调用无法回滚的问题

文章目录

    • 问题分析
    • 解决方案
    • 实现原理解析
    • 执行流程说明
    • 运行实例
      • 正常流程执行
      • 执行异常流程
    • 关键优势

在分布式系统开发中,我们经常会遇到本地事务与远程服务调用结合的场景。当本地事务包含RPC调用时,如果事务回滚,RPC调用已经执行就会导致数据不一致。本文将介绍如何优雅地解决这个问题。

问题分析

考虑以下场景:有方法A、B、C组成一个大事务,其中B方法需要调用RPC服务。如果C方法执行失败导致整个事务回滚,但RPC已经调用并提交,就会造成数据不一致。

核心问题是:RPC调用默认会在本地事务提交前执行,无法参与事务回滚

解决方案

Spring提供了事务同步机制(TransactionSynchronization),允许我们注册回调函数,在事务完成后执行特定操作。利用这个机制,我们可以确保:

只有当本地事务成功提交后,才会执行RPC调用;如果事务回滚,则不执行RPC

以下是实现代码:

package cn.bb.mydemo.service;import cn.bb.mydemo.entity.Student;
import cn.bb.mydemo.mapper.StudentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;import java.time.LocalTime;
import java.util.concurrent.CompletableFuture;@Service
public class StudentService {@Autowiredprivate StudentMapper studentMapper;@Transactional(rollbackFor = Exception.class)public void saveWithRpcAfterTx(String name) {// 1. 执行本地数据库操作Student student = new Student();student.setName(name);studentMapper.insert(student);// 2. 注册事务同步回调:在事务提交后异步执行RPCTransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {@Overridepublic void afterCommit() {// 使用CompletableFuture异步执行RPC,避免阻塞事务提交CompletableFuture.runAsync(() -> doRpc(name));}});}@Transactional(rollbackFor = Exception.class)public void run(String name) {Student student = new Student();student.setName(name);studentMapper.insert(student);}@Transactional(rollbackFor = Exception.class)public void allRun() {// 调用不同方法组成一个大事务this.saveWithRpcAfterTx("Alice");this.run("a");this.run("b");System.out.println("本地事务已提交");// int i = 1 / 0; // 取消注释此行会触发异常,导致事务回滚}// 模拟RPC调用private void doRpc(String name) {System.out.println(LocalTime.now() + " RPC调用收到:" + name);}
}

测试代码验证实现效果:

@SpringBootTest
class TxAsyncTest {@Autowiredprivate StudentService studentService;@Testvoid shouldRpcAfterTxCommit2() throws InterruptedException {// 调用组合事务方法studentService.allRun();// 等待异步RPC执行完成Thread.sleep(20000);}
}

实现原理解析

这个解决方案的核心在于TransactionSynchronizationManagerTransactionSynchronizationAdapter的使用:

  1. TransactionSynchronizationManager:Spring提供的事务同步管理器,允许注册回调函数监听事务生命周期事件

  2. TransactionSynchronizationAdapter:事务同步适配器,我们可以重写其中的关键方法:

    • afterCommit():事务成功提交后执行
    • afterCompletion():事务完成后执行(无论成功或失败)
    • beforeCommit():事务提交前执行
  3. 异步执行:使用CompletableFuture.runAsync()确保RPC调用不会阻塞事务提交过程

执行流程说明

当调用allRun()方法时,执行流程如下:

  1. 开启数据库事务
  2. 执行saveWithRpcAfterTx():插入数据库记录并注册事务同步回调
  3. 执行run()两次:插入两条额外记录
  4. 如果没有异常,事务提交
  5. 事务提交后,触发注册的afterCommit()回调
  6. 异步执行RPC调用
  7. 如果任何步骤发生异常,事务回滚,不会触发RPC调用

运行实例

正常流程执行

在这里插入图片描述

在这里插入图片描述
新增了ab 并且 rpc是最后被调用的 虽然这个方法被放在了中间

执行异常流程

在这里插入图片描述
在这里插入图片描述
数据也没有添加什么 事务被回滚了 这就保证了我们的需求【当事务被提交 rpc才被调用 否则错误就不执行rpc 防止重复数据的生成】

关键优势

  1. 数据一致性:确保本地事务与RPC调用的最终一致性
  2. 非侵入性:不需要修改现有事务管理代码
  3. 异步执行:不影响事务性能
  4. 简单可靠:基于Spring内置机制,无需额外框架

这种方法特别适合那些需要保证本地数据与远程服务数据一致性的场景,是解决大事务中RPC无法回滚问题的优雅方案。

http://www.dtcms.com/a/293746.html

相关文章:

  • 零基础学编程,编程从入门到精通系列教程,附:编程工具箱之时间计算构件的用法#零基础自学编程 学习计划#新手学编程 高效学习方法
  • HF83311_VB1/HF83311Q_VB1:高性能USB HiFi音频解码器固件技术解析
  • Leetcode-15. 三数之和
  • 《计算机“十万个为什么”》之 [特殊字符] 深浅拷贝 引用拷贝:内存世界的复制魔法 ✨
  • 1.1 Deep learning?pytorch ?深度学习训练出来的模型通常有效但无法解释合理性? 如何 解释?
  • 英语词汇积累Day1-10(summary)
  • Django实战:Python代码规范指南
  • 【Java】Reflection反射(代理模式)
  • 算法竞赛备赛——【图论】最小生成树
  • 《元素周期表》超高清PDF
  • IDEA如何管理多个Java版本。
  • STM32 基础知识 定时器【概念】
  • 基于PyTorch的多视角二维流场切片三维流场预测模型
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 主页-微博点赞量Top6实现
  • 19.动态路由协议基础
  • 备受关注的“Facebook Email Scraper”如何操作?
  • 开源 Arkts 鸿蒙应用 开发(十)通讯--Http
  • 腾讯云推出CodeBuddy:革新AI全栈开发体验
  • 第六章 W55MH32 UDP Multicast示例
  • 神经架构搜索革命:从动态搜索到高性能LLM的蜕变之路
  • AI 搜索引擎:让信息“长脑子”而不是“堆数据”
  • 解决 i.MX6ULL 通过 ADB 连接时权限不足问题 not in the plugdev group
  • 网络调制技术对比表
  • Numpy 库 矩阵数学运算,点积,文件读取和保存等
  • 线段树学习笔记 - 练习题(1)
  • iOS 性能监控 苹果手机后台运行与能耗采样实战指南
  • 沉浸式文旅新玩法-基于4D GS技术的真人数字人赋能VR体验升级
  • 深度相机---像素转物理尺寸
  • 【基于OpenCV的图像处理】图像预处理之二值化处理以及图像的仿射变换
  • 基于Python flask的常用AI工具功能数据分析与可视化系统设计与实现,技术包括LSTM、SVM、朴素贝叶斯三种算法,echart可视化