日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

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

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

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

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

一、案例背景

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

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

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

二、確定方案

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

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

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

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

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

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

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

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

三、TransactionSynchronizationManager顯神威

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

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

我們先看下這個方法的源碼:Swr28資訊網——每日最新資訊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,其源碼如下所示:Swr28資訊網——每日最新資訊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,則代表當前有事務。因此,結合這兩個方法我們是指能解決我們最開始提出的疑問:**要如何判斷當前是否存在事務**Swr28資訊網——每日最新資訊28at.com

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

TransactionSynchronizationManager.registerSynchronization()方法顯神威

我們來看下這個方法的源代碼:Swr28資訊網——每日最新資訊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方法,其代碼如下所示:Swr28資訊網——每日最新資訊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系列的回調Swr28資訊網——每日最新資訊28at.com

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

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

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

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

四、總結

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

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

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

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

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

標簽:
  • 熱門焦點
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
久久激情视频久久| 亚洲精品国产精品国自产在线| 欧美日韩精品久久| 欧美日韩不卡在线| 国产精品日韩在线| 一区二区三区在线视频免费观看 | 国产亚洲精久久久久久| 国产主播一区二区三区| 亚洲国产精品黑人久久久| 一区二区福利| 欧美在线观看一区二区三区| 久久一区二区三区四区五区| 欧美日韩一区自拍| 国产在线拍偷自揄拍精品| 日韩亚洲欧美精品| 久久精品视频一| 欧美日韩在线第一页| 国产亚洲欧美aaaa| 亚洲欧洲在线免费| 性久久久久久| 欧美精品一区二区高清在线观看| 国产精品色网| 亚洲黄色视屏| 欧美一区1区三区3区公司| 欧美成人免费在线观看| 国产精品中文字幕在线观看| 91久久精品一区| 欧美在线一二三四区| 欧美日韩激情网| 伊人狠狠色丁香综合尤物| 亚洲一区二区三区精品在线观看| 久久久久综合| 国产精品免费久久久久久| 91久久精品日日躁夜夜躁欧美| 欧美亚洲一级片| 欧美日韩国产综合网 | 欧美性片在线观看| 在线看视频不卡| 亚洲欧美日韩另类| 欧美精品www在线观看| 国产综合精品一区| 亚洲一区欧美| 欧美精品激情| 一区二区三区在线视频观看| 亚洲欧美在线播放| 欧美日韩一区二区三区在线| 亚洲国产免费| 久久精品日韩欧美| 国产精品久久中文| 一本大道久久精品懂色aⅴ| 欧美~级网站不卡| 国产亚洲一级| 亚洲欧美视频在线观看| 欧美日韩免费高清| 亚洲激情网站免费观看| 久久久久久久综合狠狠综合| 国产欧美日韩一区二区三区| 亚洲一区精品电影| 欧美色123| 99re热这里只有精品免费视频| 乱人伦精品视频在线观看| 国产亚洲欧美aaaa| 亚洲资源av| 国产精品啊啊啊| 一本色道久久88综合日韩精品| 欧美国产精品| 亚洲国产成人在线视频| 久久一区中文字幕| 韩日视频一区| 久久精品国产一区二区三| 国产日韩精品一区二区三区| 欧美一区视频在线| 国产视频亚洲| 久久久精彩视频| 国产专区一区| 久久九九国产精品怡红院| 国产伦精品一区二区三区在线观看| 亚洲一级电影| 国产精品高潮呻吟| 亚洲淫性视频| 国产精品一级在线| 香蕉av福利精品导航| 国产精品自在欧美一区| 欧美一区成人| 国产一区再线| 久久人人看视频| 在线观看视频一区二区| 麻豆精品在线播放| 亚洲人成毛片在线播放| 欧美激情亚洲一区| 99国产精品久久| 国产精品成人一区二区网站软件| 亚洲一区精品电影| 国产日韩欧美另类| 久久亚洲不卡| 亚洲人成人一区二区三区| 欧美激情国产日韩| 99视频日韩| 国产精品你懂的在线| 欧美一区午夜精品| 影视先锋久久| 欧美激情综合在线| 亚洲天堂网站在线观看视频| 国产精品午夜av在线| 久久黄色级2电影| 亚洲国产精品高清久久久| 欧美精品福利在线| 亚洲专区一区| 极品尤物av久久免费看| 欧美成人午夜剧场免费观看| 99精品欧美一区二区三区综合在线| 欧美性一区二区| 欧美在线高清视频| 在线视频国产日韩| 欧美日韩国产综合视频在线观看| 亚洲欧美在线看| 在线日本成人| 欧美四级在线观看| 久久动漫亚洲| 亚洲全部视频| 国产精品手机在线| 毛片一区二区三区| 亚洲深夜福利视频| 国内精品视频一区| 欧美日韩精品免费观看| 欧美亚洲一区在线| 亚洲国产精品久久精品怡红院| 欧美日韩在线观看一区二区三区 | 葵司免费一区二区三区四区五区| 日韩性生活视频| 国产日韩欧美精品在线| 女女同性女同一区二区三区91| 中国成人在线视频| 极品日韩久久| 国产精品国色综合久久| 久久综合久色欧美综合狠狠| 一区二区欧美激情| 激情国产一区| 国产精品久久久久久户外露出| 久久久精品国产99久久精品芒果| 日韩视频一区| 狠狠综合久久av一区二区小说| 欧美日韩视频专区在线播放| 久久精品在线播放| 亚洲视频第一页| 在线不卡a资源高清| 国产精品久久国产精麻豆99网站| 久久综合九色综合久99| 亚洲男人的天堂在线aⅴ视频| 亚洲福利视频网站| 国产欧美日韩一区| 欧美日韩亚洲一区在线观看| 久久视频一区二区| 亚洲欧美日韩精品久久奇米色影视| 亚洲国产一区二区a毛片| 国产日韩在线视频| 国产精品videosex极品| 免费日韩视频| 久久精品欧美日韩| 亚洲影院在线观看| 亚洲美女av黄| 一区二区三区在线观看欧美| 国产精品一卡二卡| 欧美视频观看一区| 欧美国产日本在线| 久久综合国产精品| 久久精品亚洲精品国产欧美kt∨| 亚洲午夜国产成人av电影男同| 亚洲欧洲精品一区二区| 激情文学一区| 国产一区二区日韩精品欧美精品 | 黄色国产精品| 国产日韩精品一区二区| 国产精品成人一区| 欧美日韩国产一区| 欧美激情精品久久久久久蜜臀| 久久久精品免费视频| 午夜一区在线| 亚洲一区欧美一区| 欧美日韩免费观看一区=区三区| 久久蜜桃资源一区二区老牛 | 男同欧美伦乱| 浪潮色综合久久天堂| 久久精品99国产精品酒店日本| 亚洲欧美国产毛片在线| 亚洲一区二区三区视频| 亚洲视频www| 亚洲作爱视频| 亚洲美女中文字幕| 亚洲精品久久久久中文字幕欢迎你| 亚洲福利国产| 亚洲国产精品专区久久| 亚洲国产精品黑人久久久| 在线观看免费视频综合| 伊人久久成人| 在线看一区二区| 1769国内精品视频在线播放| 在线不卡视频| 在线观看视频一区二区| 在线观看免费视频综合| 亚洲激情网址| 日韩视频在线一区二区| 一本色道综合亚洲| 在线一区免费观看|