解決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.pswp.cn/diannao/92466.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/92466.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/92466.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

sqli-labs通關筆記-第13關 POST報錯型注入(單引號括號閉合 手工注入+腳本注入兩種方法)

目錄 一、字符型注入 二、limit函數 三、GET方法與POST方法 四、源碼分析 1、代碼審計 2、SQL注入安全分析 3、報錯型注入與聯合注入 五、滲透實戰 1、進入靶場 2、注入點分析 (1)SQL語句 (2)admin) #注入探測 &…

康復器材動靜態性能測試臺:精準檢測,為康復器械安全保駕護航

在康復醫療領域,無論是輪椅、拐杖、假肢還是康復床,每一件器械的強度與穩定性都直接關系到使用者的安全與康復效果。如何確保這些器械在實際使用中經得起反復考驗?Delta德爾塔儀器推出的康復器材動靜態性能測試臺,憑借其高精度、智…

vue3中el-table表頭篩選

效果如下&#xff0c;可以勾選表頭進行隱藏&#xff0c;也可以對表頭進行拖動排序index主界面 <script> let tempHead []; const showFilter ref<boolean>(false); let tableHeadList ref<TableHeadItem[]>([{ prop: "displayId", label: "…

數據結構 之 【排序】(直接選擇排序、堆排序、冒泡排序)

目錄 1.直接選擇排序 1.1直接選擇排序的思想 1.2直接選擇排序的代碼邏輯 1.3完整排序代碼 1.3.1一次只選一個最值 1.3.2一次篩選出兩個最值 1.4直接選擇排序的時間復雜度與空間復雜度 2.堆排序 2.1堆排序的思想 2.2堆排序的具體步驟 2.3堆排序圖解 2.4完整排序代碼…

用手機當外掛-圖文并茂做報告紀要

前陣參加一個峰會,看到演講嘉賓每翻一頁PPT,下面的觀察就舉起手機一頓拍。實話說這種拍下來的,難說還會拿出來看,而且再看的時候也未必能對應到當時主講人的一些解釋 。 如果現場將圖片保存到筆記本電腦,并快速記錄關鍵信息,這樣聽完一個報告可能就直接輸出一篇報道了。 有…

Vue的ubus emit/on使用

這段代碼是 Vue.js 組件中的 mounted 生命周期鉤子函數&#xff0c;主要作用是監聽一個名為 “macSelectData” 的全局事件。具體行為如下&#xff1a;分步解釋&#xff1a;mounted() 生命周期鉤子 當組件被掛載到 DOM 后&#xff0c;Vue 會自動調用 mounted() 方法。這里常用于…

rsync報錯解決

問題說明 [rootlocalhost shyn]# rsync -avz --checksum "root192.168.159.133:/tmp/shyn" "/tmp /shyn"WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! …

ArKTS: DAL,Model,BLL,Interface,Factory using SQLite

HarmonyOS 用ohos.data.rdb 用DBHelper.ets 共用調用SQLite 庫&#xff0c;進行DAL,Model,BLL,Interface,Factory 框架模式&#xff0c;表為CREATE TABLE IF NOT EXISTS signInRecord ( id INTEGER PRIMARY KEY AUTOINCREMENT, employeeId TEXT NOT NULL, employeeName TEXT NO…

MySQL JSON 數據類型用法及與傳統JSON字符串的對比 JSON數據類型簡介

文章目錄前言1. 基本用法JSON數據類型 vs 傳統JSON字符串1. 存儲方式2. 查詢方式對比3. 索引支持JSON存儲對象和數組的性能考慮1. 存儲對象2. 存儲數組性能對比總結最佳實踐建議前言 MySQL從 5.7 版本開始引入了 JSON 數據類型&#xff0c;專門用于存儲 JSON 格式的數據。與傳…

C++:list(1)list的使用

list的使用一.list基本的結構1.環狀雙向鏈表2.哨兵節點3.迭代器4.節點結構5.鏈表遍歷6.迭代器失效二.list的基本使用1.test01函數&#xff1a;主要測試std::list的初始化方式及遍歷2.test02函數&#xff1a;主要測試std::list的常用成員函數操作3.測試結果如下三.list的其他操作…

ArcGIS地形起伏度計算

地形起伏度計算地形起伏度步驟1&#xff1a;計算最大值。步驟2&#xff1a;計算最小值。步驟3&#xff1a;計算地形起伏度。地形起伏度、地形粗糙度、地表切割深度和高程變異系數均為坡面復雜度因子&#xff0c;是一種宏觀的地形信息因子&#xff0c;反映的是較大的區域內地表坡…

llama factory新手初步運行完整版

1、新建conda環境名稱為llama_factory&#xff0c;并激活 conda create -n llama_factory python3.10 conda activate llama_factory2、激活后可檢查內部包是否純凈&#xff0c;要確保環境內包較純凈&#xff0c;不然后續安裝對應包會出現一系列水土不服的問題&#xff0c;導致…

Tomcat與JDK版本對照全解析:避坑指南與生產環境選型最佳實踐

&#x1f49d;&#x1f49d;&#x1f49d;歡迎蒞臨我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 持續學習&#xff0c;不斷…

短視頻矩陣的未來前景:機遇無限,挑戰并存

在當今數字化信息飛速傳播的時代&#xff0c;短視頻以其獨特的魅力迅速席卷全球&#xff0c;成為人們獲取信息、娛樂消遣的重要方式之一。短視頻矩陣作為一種高效的內容傳播與運營模式&#xff0c;正逐漸展現出其強大的影響力和潛力。本文將深入探討短視頻矩陣的未來前景&#…

【數據結構】哈希——位圖與布隆過濾器

目錄 位圖&#xff1a; 引入 位圖實現&#xff1a; 位圖的結構 插入數據(標記數據) 刪除數據(重置數據) 查找數據 位圖完整代碼&#xff1a; 位圖的優缺點&#xff1a; 布隆過濾器&#xff1a; 引入 布隆過濾器實現&#xff1a; 布隆過濾器的結構&#xff1a; 插入…

本地運行C++版StableDiffusion!開源應用StableVerce發布

本地運行C版StableDiffusion&#xff01;開源應用StableVerce發布 StableVerse是一個用C開發的本地運行的圖形工具。適合初學者快速入門&#xff1b;適用于辦公室工作人員的文本和圖像制作的小規模計算能力場景。 開源地址&#xff1a;https://github.com/kelvin-luo/StableVer…

OpenLayers 快速入門(七)矢量數據

看過的知識不等于學會。唯有用心總結、系統記錄&#xff0c;并通過溫故知新反復實踐&#xff0c;才能真正掌握一二 作為一名摸爬滾打三年的前端開發&#xff0c;開源社區給了我飯碗&#xff0c;我也將所學的知識體系回饋給大家&#xff0c;助你少走彎路&#xff01; OpenLayers…

【PTA數據結構 | C語言版】關于堆的判斷

本專欄持續輸出數據結構題目集&#xff0c;歡迎訂閱。 文章目錄題目代碼題目 將一系列給定數字順序插入一個初始為空的最小堆。隨后判斷一系列相關命題是否為真。命題分下列幾種&#xff1a; x is the root&#xff1a;x是根結點&#xff1b;x and y are siblings&#xff1a…

[CH582M入門第十步]藍牙從機

前言 學習目標: 1、初步了解BLE協議 2、BLE從機代碼解析 3、使用手機藍牙軟件控制CH582M從機LED亮滅一、藍牙介紹 藍牙(Bluetooth)是一種短距離無線通信技術,主要用于設備之間的數據傳輸和通信。它由愛立信(Ericsson)于1994年提出,現由藍牙技術聯盟(Bluetooth SIG)維…

力扣(LeetCode) ——輪轉數組(C語言)

題目&#xff1a;輪轉數組 給定一個整數數組 nums&#xff0c;將數組中的元素向右輪轉 k 個位置&#xff0c;其中 k 是非負數。 示例1&#xff1a; 輸入&#xff1a; nums [1,2,3,4,5,6,7]&#xff0c;k 3 輸出&#xff1a; [5,6,7,1,2,3,4] 解釋&#xff1a; 向右輪轉 1 步:…