AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

事務鉤子函數,打造高效支付系統

來源: 責編: 時間:2024-05-09 09:23:03 126觀看
導讀今天,我繼續安利一個獨門絕技:Spring 事務的鉤子函數。單純的講技術可能比較枯燥乏味。接下來,我將以一個實際的案例來描述Spring事務鉤子函數的正確使用姿勢。一、案例背景拿支付系統相關的業務來舉例。在支付系統中,我

今天,我繼續安利一個獨門絕技:Spring 事務的鉤子函數。單純的講技術可能比較枯燥乏味。接下來,我將以一個實際的案例來描述Spring事務鉤子函數的正確使用姿勢。B8d28資訊網——每日最新資訊28at.com

一、案例背景

拿支付系統相關的業務來舉例。在支付系統中,我們需要記錄每個賬戶的資金流水(記錄用戶A因為哪個操作扣了錢,因為哪個操作加了錢),這樣我們才能對每個賬戶的賬做到心中有數,對于支付系統而言,資金流水的數據可謂是最重要的。因此,為了防止支付系統的老大徇私舞弊,CTO提了一個流水存檔的需求:要求支付系統對每個賬戶的資金流水做一份存檔,要求支付系統在寫流水的時候,把流水相關的信息以消息的形式推送到kafka,由存檔系統消費這個消息并落地到庫里(這個庫只有存檔系統擁有寫權限)。整個需求的流程如下所示:B8d28資訊網——每日最新資訊28at.com

圖片圖片B8d28資訊網——每日最新資訊28at.com

整個需求的流程還是比較簡單的,考慮到后續會有其他事業部也要進行數據存檔操作,CTO建議支付系統團隊內部開發一個二方庫,這個二方庫的主要功能就是發送消息到kafka中去。B8d28資訊網——每日最新資訊28at.com

二、確定方案

既然要求開發一個二方庫,因此,我們需要考慮如下幾件事情:B8d28資訊網——每日最新資訊28at.com

1、技術棧使用的springboot,因此,這里最好以starter的方式提供B8d28資訊網——每日最新資訊28at.com

2、二方庫需要發送消息給kafka,最好是二方庫內部基于kafka生產者的api創建生產者,不要使用Spring自帶的kafkaTemplate,因為集成方有可能已經使用了kafkaTemplate。不能與集成方造成沖突。B8d28資訊網——每日最新資訊28at.com

3、減少對接方的集成難度、學習成本,最好是提供一個簡單實用的api,業務側能簡單上手。B8d28資訊網——每日最新資訊28at.com

4、發送消息這個操作需要支持事務,盡量不影響主業務B8d28資訊網——每日最新資訊28at.com

在上述的幾件事情中,最需要注意的應該就是第4點:發送消息這個操作需要支持事務,盡量不影響主業務。這是什么意思呢?首先,盡量不影響主業務,這個最簡單的方式就是使用異步機制。其次,需要支持事務是指:假設我們的api是在事務方法內部調用的,那么我們需要保證事務提交后再執行這個api。那么,我們的流水落地api應該要有這樣的功能:B8d28資訊網——每日最新資訊28at.com

圖片圖片B8d28資訊網——每日最新資訊28at.com

內部可以判斷當前是否存在事務,如果存在事務,則需要等事務提交后再異步發送消息給kafka。如果不存在事務則直接異步發送消息給kafka。而且這樣的判斷邏輯得放在二方庫內部才行。那現在擺在我們面前的問題就是:我要如何判斷當前是否存在事務,以及如何在事務提交后再觸發我們自定義的邏輯呢?B8d28資訊網——每日最新資訊28at.com

三、TransactionSynchronizationManager顯神威

這個類內部所有的變量、方法都是static修飾的,也就是說它其實是一個工具類。是一個事務同步器。下述是流水落地API的偽代碼,這段代碼就解決了我們上述提到的疑問:B8d28資訊網——每日最新資訊28at.com

private final ExecutorService executor = Executors.newSingleThreadExecutor();public void sendLog() {    // 判斷當前是否存在事務    if (!TransactionSynchronizationManager.isSynchronizationActive()) {        // 無事務,異步發送消息給kafka                executor.submit(() -> {            // 發送消息給kafka            try {                // 發送消息給kafka            } catch (Exception e) {                // 記錄異常信息,發郵件或者進入待處理列表,讓開發人員感知異常            }        });        return;    }    // 有事務,則添加一個事務同步器,并重寫afterCompletion方法(此方法在事務提交后會做回調)    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {        @Override        public void afterCompletion(int status) {            if (status == TransactionSynchronization.STATUS_COMMITTED) {                // 事務提交后,再異步發送消息給kafka                executor.submit(() -> {                    try {                     // 發送消息給kafka                    } catch (Exception e) {                     // 記錄異常信息,發郵件或者進入待處理列表,讓開發人員感知異常                    }                });            }        }    });}

代碼比較簡單,其主要是TransactionSynchronizationManager的使用。B8d28資訊網——每日最新資訊28at.com

3.1、判斷是否存在事務?TransactionSynchronizationManager.isSynchronizationActive() 方法顯神威

我們先看下這個方法的源碼:B8d28資訊網——每日最新資訊28at.com

// TransactionSynchronizationManager.java類內部的部分代碼private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =   new NamedThreadLocal<>("Transaction synchronizations");public static boolean isSynchronizationActive() {    return (synchronizations.get() != null);}

很明顯,synchronizations是一個線程變量(ThreadLocal)。那它是在什么時候set進去的呢?這里的話,可以參考下這個方法:org.springframework.transaction.support.TransactionSynchronizationManager#initSynchronization,其源碼如下所示:B8d28資訊網——每日最新資訊28at.com

/**  * Activate transaction synchronization for the current thread.  * Called by a transaction manager on transaction begin.  * @throws IllegalStateException if synchronization is already active  */public static void initSynchronization() throws IllegalStateException {    if (isSynchronizationActive()) {        throw new IllegalStateException("Cannot activate transaction synchronization - already active");    }    logger.trace("Initializing transaction synchronization");    synchronizations.set(new LinkedHashSet<>());}

由源碼中的注釋也可以知道,它是在事務管理器開啟事務時調用的。換句話說,只要我們的程序執行到帶有事務特性的方法時,就會在線程變量中放入一個LinkedHashSet,用來標識當前存在事務。只要isSynchronizationActive返回true,則代表當前有事務。因此,結合這兩個方法我們是指能解決我們最開始提出的疑問:**要如何判斷當前是否存在事務**B8d28資訊網——每日最新資訊28at.com

3.2、如何在事務提交后觸發自定義邏輯?

TransactionSynchronizationManager.registerSynchronization()方法顯神威

我們來看下這個方法的源代碼:B8d28資訊網——每日最新資訊28at.com

/**  * Register a new transaction synchronization for the current thread.  * Typically called by resource management code.  * <p>Note that synchronizations can implement the  * {@link org.springframework.core.Ordered} interface.  * They will be executed in an order according to their order value (if any).  * @param synchronization the synchronization object to register  * @throws IllegalStateException if transaction synchronization is not active  * @see org.springframework.core.Ordered  */public static void registerSynchronization(TransactionSynchronization synchronization)    throws IllegalStateException {    Assert.notNull(synchronization, "TransactionSynchronization must not be null");    if (!isSynchronizationActive()) {        throw new IllegalStateException("Transaction synchronization is not active");    }    synchronizations.get().add(synchronization);}

這里又使用到了synchronizations線程變量,我們在判斷是否存在事務時,就是判斷這個線程變量內部是否有值。那我們現在想在事務提交后觸發自定義邏輯和這個有什么關系呢?我們在上面構建流水落地api的偽代碼中有向synchronizations內部添加了一個TransactionSynchronizationAdapter,內部并重寫了afterCompletion方法,其代碼如下所示:B8d28資訊網——每日最新資訊28at.com

TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {    @Override    public void afterCompletion(int status) {        if (status == TransactionSynchronization.STATUS_COMMITTED) {            // 事務提交后,再異步發送消息給kafka            executor.submit(() -> {                    try {                     // 發送消息給kafka                    } catch (Exception e) {                     // 記錄異常信息,發郵件或者進入待處理列表,讓開發人員感知異常                    }            });        }    }});

我們結合registerSynchronization的源碼來看,其實這段代碼主要就是向線程變量內部的LinkedHashSet添加了一個對象而已,但就是這么一個操作,讓Spring在事務執行的過程中變得“有事情可做”。這是什么意思呢?是因為Spring在執行事務方法時,對于操作事務的每一個階段都有一個回調操作,比如:trigger系列的回調B8d28資訊網——每日最新資訊28at.com

圖片圖片B8d28資訊網——每日最新資訊28at.com

invoke系列的回調B8d28資訊網——每日最新資訊28at.com

圖片圖片B8d28資訊網——每日最新資訊28at.com

而我們現在的需求就是在事務提交后觸發自定義的函數,那就是在invokeAfterCommit和invokeAfterCompletion這兩個方法來選了。首先,這兩個方法都會拿到所有TransactionSynchronization的集合(其中會包括我們上述添加的TransactionSynchronizationAdapter)。但是要注意一點:invokeAfterCommit只能拿到集合,invokeAfterCompletion除了集合還有一個int類型的參數,而這個int類型的參數其實是當前事務的一種狀態。也就是說,如果我們重寫了invokeAfterCompletion方法,我們除了能拿到集合外,還能拿到當前事務的狀態。因此,此時我們可以根據這個狀態來做不同的事情,比如:可以在事務提交時做自定義處理,也可以在事務回滾時做自定義處理等等。B8d28資訊網——每日最新資訊28at.com

四、總結

上面有說到,我們判斷當前是否存在事務、添加鉤子函數都是依賴線程變量的。因此,我們在使用過程中,一定要避免切換線程。否則會出現不生效的情況。B8d28資訊網——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-87482-0.html事務鉤子函數,打造高效支付系統

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: WPF UI更新技巧:掌握EventHandler的基礎與Dispatcher的高級應用

下一篇: 哈希表哪家強?幾大編程語言吵起來了!

標簽:
  • 熱門焦點
  • Mate60手機殼曝光 致敬自己的經典設計

    8月3日消息,今天下午博主數碼閑聊站帶來了華為Mate60的第三方手機殼圖,可以讓我們在真機發布之前看看這款華為全新旗艦的大致輪廓。從曝光的圖片看,Mate 60背后攝像頭面積依然
  • 分布式系統中的CAP理論,面試必問,你理解了嘛?

    對于剛剛接觸分布式系統的小伙伴們來說,一提起分布式系統,就感覺高大上,深不可測。而且看了很多書和視頻還是一臉懵逼。這篇文章主要使用大白話的方式,帶你理解一下分布式系統
  • 不容錯過的MSBuild技巧,必備用法詳解和實踐指南

    一、MSBuild簡介MSBuild是一種基于XML的構建引擎,用于在.NET Framework和.NET Core應用程序中自動化構建過程。它是Visual Studio的構建引擎,可在命令行或其他構建工具中使用
  • 虛擬鍵盤 API 的妙用

    你是否在遇到過這樣的問題:移動設備上有一個固定元素,當激活虛擬鍵盤時,該元素被隱藏在了鍵盤下方?多年來,這一直是 Web 上的默認行為,在本文中,我們將探討這個問題、為什么會發生
  • WebRTC.Net庫開發進階,教你實現屏幕共享和多路復用!

    WebRTC.Net庫:讓你的應用更親民友好,實現視頻通話無痛接入! 除了基本用法外,還有一些進階用法可以更好地利用該庫。自定義 STUN/TURN 服務器配置WebRTC.Net 默認使用 Google 的
  • 每天一道面試題-CPU偽共享

    前言:了不起:又到了每天一到面試題的時候了!學弟,最近學習的怎么樣啊 了不起學弟:最近學習的還不錯,每天都在學習,每天都在進步! 了不起:那你最近學習的什么呢? 了不起學弟:最近在學習C
  • 三星Galaxy Z Fold/Flip 5國行售價曝光 :最低7499元/12999元起

    據官方此前宣布,三星將于7月26日也就是明天在韓國首爾舉辦Unpacked活動,屆時將帶來帶來包括Galaxy Buds 3、Galaxy Watch 6、Galaxy Tab S9、Galaxy
  • 超級標準版旗艦!iQOO 11S全球首發iQOO超算獨顯芯片

    上半年已接近尾聲,截至目前各大品牌旗下的頂級旗艦都已悉數亮相,而下半年即將推出的頂級旗艦已經成為了數碼圈爆料的主流,其中就包括全新的iQOO 11S系
  • 2022爆款:ROG魔霸6 冰川散熱系統持續護航

    喜逢開學季,各大商家開始推出自己的新產品,進行打折促銷活動。對于忠實的端游愛好者來說,能夠擁有一款夢寐以求的筆記本電腦是一件十分開心的事。但是現在的
Top