利用事務鉤子函數解決業務異步發送問題

利用事務鉤子函數解決業務異步發送問題

  • 一、問題背景
  • 二、實現方案
    • 1、生產者代碼
    • 2、消費者代碼
  • 三、測試與驗證
    • 1、未開啟事務場景
    • 2、開啟事務場景
  • 四、項目結構及源碼

一、問題背景

在這里插入圖片描述
在某項業務中,需要在事務完成后,寫入日志到某數據庫中。需要要么都成功,要么都失敗,而且需要異步實現。在不考慮分布式事務框架下,如何實現這個業務功能呢?

二、實現方案

前提需要啟動kafka_2.12-3.9.1內置的zookeeper和kafka。
在這里插入圖片描述
在這里插入圖片描述
在kafka創建好topic

kafka-topics.bat --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic testTopic

在這里插入圖片描述
在這里插入圖片描述
可以利用事務鉤子函數實現異步發送,保證同時成功和失敗。注冊事務鉤子,在事務提交或回滾后執行。

if (!TransactionSynchronizationManager.isSynchronizationActive()) {// 調用異步方法發送日志System.out.println("事務未開啟");// 異步發送日志(解決由于同一個類內部方法調用不會創建代理,所以aop不生效,則@Async注解無作用問題)kafkaSender.send();} else {// 注冊事務鉤子,在事務提交或回滾后執行TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {@Overridepublic void afterCompletion(int status) {System.out.println("事務開啟并執行完畢");// 異步發送日志(解決由于同一個類內部方法調用不會創建代理,所以aop不生效,則@Async注解無作用問題)kafkaSender.send();}});}

1、生產者代碼

KafkaController

@RestController
public class KafkaController {@Autowiredprivate TestService testService;@GetMapping("/send/{type}")public String sendMessageToKafka(@PathVariable int type) {if(type == 1){// 模擬執行事務未開啟的業務邏輯testService.executeServiceNoTranscational(type);}else{// 模擬執行事務開啟的業務邏輯testService.executeService(type);}//模擬還要執行其他的serviceSystem.out.println("執行其他業務邏輯");return "ok";}
}

KafkaSender

@Component
@Slf4j
public class KafkaSender {@Resourceprivate KafkaTemplate<String, Object> kafkaTemplate;@Asyncpublic void send() {System.out.println("異步發送消息");Map<String, String> messageMap = new HashMap<>();messageMap.put("log", "日志:執行完成");ObjectMapper objectMapper = new ObjectMapper();String data;try {data = objectMapper.writeValueAsString(messageMap);} catch (JsonProcessingException e) {throw new RuntimeException(e);}String key = String.valueOf(UUID.randomUUID());//kakfa的推送消息方法有多種,可以采取帶有任務key的,也可以采取不帶有的(不帶時默認為null)this.send("testTopic", key, data);}public void send(String topic, String key, String data) {//發送消息CompletableFuture<SendResult<String, Object>> completable = kafkaTemplate.send(topic, key, data);completable.whenCompleteAsync((result, ex) -> {if (null == ex) {log.info(topic + "生產者發送消息成功:" + result.toString());} else {log.info(topic + "生產者發送消息失敗:" + ex.getMessage());}});}
}

LogService注冊鉤子函數,異步發送

@Service
public class LogService {@AutowiredKafkaSender kafkaSender;public void sendLogAsync() {if (!TransactionSynchronizationManager.isSynchronizationActive()) {// 調用異步方法發送日志System.out.println("事務未開啟");// 異步發送日志(解決由于同一個類內部方法調用不會創建代理,所以aop不生效,則@Async注解無作用問題)kafkaSender.send();} else {// 注冊事務鉤子,在事務提交或回滾后執行TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {@Overridepublic void afterCompletion(int status) {System.out.println("事務開啟并執行完畢");// 異步發送日志(解決由于同一個類內部方法調用不會創建代理,所以aop不生效,則@Async注解無作用問題)kafkaSender.send();}});}}
}

TestService

@Service
public class TestService {@AutowiredLogService logService;@Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)public void executeService(int type){System.out.println("執行業務邏輯");/*System.out.println("業務執行完成");if (!TransactionSynchronizationManager.isSynchronizationActive()) {// 調用異步方法發送日志System.out.println("事務未開啟");}else{System.out.println("事務已開啟");}*/logService.sendLogAsync();}public void executeServiceNoTranscational(int type){System.out.println("業務執行完成");if (!TransactionSynchronizationManager.isSynchronizationActive()) {// 調用異步方法發送日志System.out.println("事務未開啟");}else{System.out.println("事務已開啟");}logService.sendLogAsync();}
}

2、消費者代碼

KafkaConfig

@Configuration
@EnableKafka
public class KafkaConfig {@Beanpublic KafkaReceiver listener() {return new KafkaReceiver();}
}

KafkaReceiver

@Component
@Slf4j
public class KafkaReceiver {/*** 下面的主題是一個數組,可以同時訂閱多主題,只需按數組格式即可,也就是用","隔開*/@KafkaListener(topics = {"testTopic"})public void receive(ConsumerRecord<?, ?> record){log.info("消費者收到的消息key: " + record.key());log.info("消費者收到的消息value: " + record.value().toString());}
}

三、測試與驗證

1、未開啟事務場景

在這里插入圖片描述
生產者執行結果
請添加圖片描述
請添加圖片描述
消費者執行結果
請添加圖片描述

2、開啟事務場景

生產者執行結果
請添加圖片描述
消費者執行結果
請添加圖片描述

四、項目結構及源碼

在這里插入圖片描述

源碼下載,歡迎star!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/87373.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/87373.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/87373.shtml

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

相關文章

uniapp選擇相冊

概述 一款針對Android平臺下的圖片選擇器&#xff0c;支持從相冊獲取圖片、視頻、音頻&拍照&#xff0c;支持裁剪(單圖or多圖裁剪)、壓縮、主題自定義配置等功能&#xff0c;支持動態獲取權限&適配Android 5.0系統的開源圖片選擇框架。 支持Uniapp和Uniapp X下的Vue2、…

MAC 多應用切換技巧,單應用切換技巧

在 Mac 上&#xff0c;有幾種快捷鍵可以幫助你快速切換應用程序窗口&#xff1a; 1. Command (?) Tab - 這是最常用的快捷鍵&#xff0c;用于在打開的應用程序之間進行循環切換。按住 Command 鍵不放&#xff0c;然后反復按下 Tab 鍵可以選擇下一個應用程序。當你松開 Comm…

SpringBoot+本地部署大模型實現知識庫功能

SpringBoot本地部署大模型實現RAG知識庫功能 1、Linux系統部署本地大模型1.1 安裝ollama1.2 啟動ollama1.3 下載deepseek模型 2、Springboot代碼調用本地模型實現基礎問答功能3、集成向量數據庫4、知識庫數據喂取5、最終實現RAG知識庫功能 1、Linux系統部署本地大模型 1.1 安裝…

嵌入式原理與應用篇---ARM

ARM 架構的 STM32 系列微控制器廣泛應用于嵌入式系統開發&#xff0c;理解其匯編語言指令對于優化性能、訪問硬件底層非常重要。下面詳細解釋常見的 ARM 匯編指令及其使用實例。 數據處理指令 1. MOV&#xff08;移動&#xff09; 功能&#xff1a;將立即數或寄存器值復制到…

【RHCSA-Linux考試題目筆記(自用)】servera的題目

一、開始 1、啟動rhcsa環境 2、點擊題目&#xff0c;看題 3、通過控制器來啟動所有虛擬機 控制器 打開后點start&#xff0c;然后ok 之后進入一個有classroom、servera、serverb&#xff08;考試不一定叫這些名&#xff0c;但大差不差&#xff09;什么之類的界面&#xff0c;…

SpringBoot項目使用arthas-tunnel-server

參考官網Arthas Spring Boot Starter | arthas Spring Boot系列之使用Arthas Tunnel Server 進行遠程調試實踐-騰訊云開發者社區-騰訊云 springBoot項目, 增加maven依賴 <dependency><groupId>com.taobao.arthas</groupId><artifactId>arthas-sprin…

Modbus TCP 進階:基于以太網的遠程設備控制(二)

基于 Modbus TCP 的遠程設備控制實戰 &#xff08;一&#xff09;硬件與網絡搭建實操 1. 設備選型與連接 在工業現場&#xff0c;根據遠程控制需求進行設備選型至關重要 。對于傳感器&#xff0c;若要監測溫度&#xff0c;可選擇高精度的熱電偶傳感器&#xff0c;如 K 型熱電…

分庫分表之實戰-sharding-JDBC

大家好&#xff0c;我是工藤學編程 &#x1f989;一個正在努力學習的小博主&#xff0c;期待你的關注實戰代碼系列最新文章&#x1f609;C實現圖書管理系統&#xff08;Qt C GUI界面版&#xff09;SpringBoot實戰系列&#x1f437;【SpringBoot實戰系列】Sharding-Jdbc實現分庫…

httpcore-nio引起的線程、fd泄露問題

依賴來源&#xff1a;httpasyncclient-4.1.4.jar 現象 程序報錯too many open files 線程數飆升、句柄數飆升 thread dump顯示大量 "I/O dispatcher 7215" #9102 prio5 os_prio0 tid0x00002b7ba036a800 nid0x6f24 runnable [0x00002b7d98d41000]java.lang.Thread.…

多線程生產者消費者模型實戰案例

多線程生產者消費者模型實戰案例 前言業務場景術前準備無鎖無事務有事務 synchronized事務在鎖外事務在鎖內 數據庫行鎖什么是數據庫行鎖有事務沒有事務 樂觀鎖ReentrantLock分布式鎖 前言 曾經一直有一個疑惑&#xff0c;就是關于多線程生產者消費者模型的學習過程中&#xf…

青少年編程與數學 02-022 專業應用軟件簡介 03 三維建模及動畫軟件:Autodesk Maya

青少年編程與數學 02-022 專業應用軟件簡介 03 三維建模及動畫軟件&#xff1a;Autodesk Maya 一、什么是三維建模二、什么是計算機動畫三、三維建模及動畫設計軟件的發展歷程&#xff08;一&#xff09;早期探索階段&#xff08;20世紀60年代 - 80年代&#xff09;&#xff08…

獲得 OCM 大師證書學習歷練

當我站在山城重慶的洪崖洞前&#xff0c;看著璀璨的夜景倒映在嘉陵江上&#xff0c;手中緊握著 OCM 大師證書&#xff0c;那一刻&#xff0c;備考時的艱辛與考試時的緊張都化作了滿滿的成就感。這段在重慶獲得 OCM 大師證書的經歷&#xff0c;就像一場充滿挑戰與驚喜的冒險&…

srs-gb28181 與 SRS 5.0 對 GB28181 國標支持

srs-gb28181 是基于 SRS 4.0/5.0 的國標&#xff08;GB28181&#xff09;擴展分支&#xff0c;而 SRS 5.0 官方版本也逐步增強了對 GB28181 的支持。以下是兩者的主要區別&#xff1a; 1. 功能支持對比 功能srs-gb28181&#xff08;擴展分支&#xff09;SRS 5.0&#xff08;官…

算法第18天|繼續二叉樹:修剪二叉搜索樹、將有序數組轉化為二叉搜索樹、把二叉搜索樹轉換為累加樹

今日總結&#xff1a; 1、修剪二叉搜索樹&#xff08;重點思考如何修剪&#xff09; &#xff08;1&#xff09;遞歸的返回值是什么&#xff1f;&#xff08;與插入、刪除一樣&#xff09; &#xff08;2&#xff09;遞歸的單層邏輯一定要縷清&#xff08;3中情況討論&#xff…

C# 多線程(三)線程池

目錄 1.通過TPL使用線程池 2.不使用TPL進入線程池的辦法 異步委托 3.線程池優化技術 最小線程數的工作原理 每當啟動一個新線程時&#xff0c;系統都需要花費數百微秒來分配資源&#xff0c;例如創建獨立的局部變量棧空間。默認情況下&#xff0c;每個線程還會占用約1…

學習筆記(29):訓練集與測試集劃分詳解:train_test_split 函數深度解析

學習筆記(29):訓練集與測試集劃分詳解&#xff1a;train_test_split 函數深度解析 一、為什么需要劃分訓練集和測試集&#xff1f; 在機器學習中&#xff0c;模型需要經歷兩個核心階段&#xff1a; 訓練階段&#xff1a;用訓練集數據學習特征與目標值的映射關系&#xff08;…

【全網唯一】自動化編輯器 Windows版純本地離線文字識別插件

目的 自動化編輯器超輕量級RPA工具&#xff0c;零代碼制作RPA自動化任務&#xff0c;解放雙手&#xff0c;釋放雙眼&#xff0c;輕松玩游戲&#xff0c;刷任務。本篇文章主要講解下自動化編輯器的TomatoOCR純本地離線文字識別Windows版插件如何使用和集成。 準備工作 1、下載自…

GitHub 2FA綁定

GitHub 2FA綁定 作為全球最大的代碼托管平臺&#xff0c;GitHub對賬號安全的重視程度不斷提升——自2023年3月起&#xff0c;GitHub已要求所有在GitHub.com上貢獻代碼的用戶必須啟用雙因素身份驗證&#xff08;2FA&#xff09;。如果你是符合條件的用戶&#xff0c;會收到一封…

pytest fixture基礎大全詳解

一、介紹 作用 fixture主要有兩個作用&#xff1a; 復用測試數據和環境&#xff0c;可以減少重復的代碼&#xff1b;可以在測試用例運行前和運行后設置和清理資源&#xff0c;避免對測試結果產生影響&#xff0c;同時也可以提高測試用例的運行效率。 優勢 pytest框架的fix…

Unity知識點-Renderer常用材質變量

本篇總結了Unity中renderer的3種常用的材質相關的變量&#xff1a;renderer.material,renderer.sharedMaterial,renderer.MaterialPropertyBlock。以及三者對SRPBatcher的影響。 一.介紹及對比 1.概念介紹 1.material 定義&#xff1a;material 是Render組件&#xff08;如…