最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot整合atomikos實(shí)現(xiàn)跨庫(kù)事務(wù)的詳細(xì)方案

 更新時(shí)間:2022年06月02日 11:57:10   作者:code2roc  
這篇文章主要介紹了SpringBoot整合atomikos實(shí)現(xiàn)跨庫(kù)事務(wù),業(yè)務(wù)主要涉及政府及企業(yè)且并發(fā)量不大,所以采用XA事務(wù),雖然性能有所損失,但是可以保證數(shù)據(jù)的強(qiáng)一致性,需要的朋友可以參考下

背景

框架之前完成了多數(shù)據(jù)源的動(dòng)態(tài)切換及事務(wù)的處理,想更近一步提供一個(gè)簡(jiǎn)單的跨庫(kù)事務(wù)處理功能,經(jīng)過(guò)網(wǎng)上的搜索調(diào)研,大致有XA事務(wù)/SEGA事務(wù)/TCC事務(wù)等方案,因?yàn)闃I(yè)務(wù)主要涉及政府及企業(yè)且并發(fā)量不大,所以采用XA事務(wù),雖然性能有所損失,但是可以保證數(shù)據(jù)的強(qiáng)一致性

方案設(shè)計(jì)

針對(duì)注冊(cè)的數(shù)據(jù)源拷貝一份用于XA事務(wù),使得本地事務(wù)和XA全局事務(wù)相互獨(dú)立可選擇的使用

Maven配置

引入atomikos第三方組件

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jta-atomikos</artifactId>
        </dependency>

注冊(cè)XA數(shù)據(jù)源

使用Druid連接池,需要使用DruidXADataSource數(shù)據(jù)源對(duì)象,再使用AtomikosDataSourceBean進(jìn)行包裝

注冊(cè)數(shù)據(jù)源時(shí)針對(duì)同一個(gè)連接注冊(cè)兩份,一份正常數(shù)據(jù)源,一份用于XA事務(wù)的數(shù)據(jù)源,數(shù)據(jù)源標(biāo)識(shí)區(qū)分并關(guān)聯(lián)

因?yàn)閟pring默認(rèn)注冊(cè)了XA事務(wù)管理器后,所有事務(wù)操作不再走本地事務(wù),我們通過(guò)切換不同的數(shù)據(jù)源決定走本地事務(wù)還是XA事務(wù)

 //主數(shù)據(jù)源xa模式
    @Bean
    @Qualifier("masterXADataSource")
    public DataSource masterXADataSource() {
        DruidXADataSource datasource = new DruidXADataSource();
        if(driverClassName.equals("com.mysql.cj.jdbc.Driver")){
            if(!dbUrl.contains("useOldAliasMetadataBehavior")){
                dbUrl += "&useOldAliasMetadataBehavior=true";
            }
            if(!dbUrl.contains("useAffectedRows")){
                dbUrl += "&useAffectedRows=true";
            }
        }
        datasource.setUrl(this.dbUrl);
        datasource.setUsername(username);
        datasource.setPassword(password);
        datasource.setDriverClassName(driverClassName);
        //configuration
        datasource.setInitialSize(1);
        datasource.setMinIdle(3);
        datasource.setMaxActive(20);
        datasource.setMaxWait(60000);
        datasource.setTimeBetweenEvictionRunsMillis(60000);
        datasource.setMinEvictableIdleTimeMillis(60000);
        datasource.setValidationQuery("select 'x'");
        datasource.setTestWhileIdle(true);
        datasource.setTestOnBorrow(false);
        datasource.setTestOnReturn(false);
        datasource.setPoolPreparedStatements(true);
        datasource.setMaxPoolPreparedStatementPerConnectionSize(20);
        datasource.setLogAbandoned(false); //移除泄露連接發(fā)生是是否記錄日志
        try {
            datasource.setFilters("stat,slf4j");
        } catch (SQLException e) {
            logger.error("druid configuration initialization filter", e);
        }
        datasource.setConnectionProperties("druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000");//connectionProperties);

        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
        atomikosDataSourceBean.setUniqueResourceName("master-xa");
        atomikosDataSourceBean.setXaDataSource(datasource);
        atomikosDataSourceBean.setPoolSize(5);
        atomikosDataSourceBean.setMaxPoolSize(20);
        atomikosDataSourceBean.setTestQuery("select 1");
        return atomikosDataSourceBean;
    }

注冊(cè)XA事務(wù)管理器

使用spring內(nèi)置的JtaTransactionManager事務(wù)管理器對(duì)象,設(shè)置AllowCustomIsolationLevels為true,否則指定自定義事務(wù)隔離級(jí)別會(huì)報(bào)錯(cuò)

    //xa模式全局事務(wù)管理器
    @Bean(name = "jtaTransactionManager")
    public PlatformTransactionManager transactionManager() throws Throwable {
        UserTransactionManager userTransactionManager = new UserTransactionManager();
        UserTransaction userTransaction = new UserTransactionImp();
        JtaTransactionManager jtaTransactionManager =  new JtaTransactionManager(userTransaction, userTransactionManager);
        jtaTransactionManager.setAllowCustomIsolationLevels(true);
        return jtaTransactionManager;
    }

定義XA事務(wù)切面

自定義注解@GlobalTransactional并定義對(duì)應(yīng)切面,使用指定注解時(shí)在ThreadLocal變量值進(jìn)行標(biāo)識(shí),組合

@Transactional注解指定XA事務(wù)管理器,在切換數(shù)據(jù)原時(shí)判斷當(dāng)前是否在XA事物中,從而切換不同的數(shù)據(jù)源

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Transactional(rollbackFor = Exception.class,isolation = Isolation.READ_UNCOMMITTED,transactionManager = "jtaTransactionManager")
public @interface GlobalTransactional {
}
@Aspect
@Component
@Order(value = 99)
public class GlobalTransitionAspect {
    private static Logger logger = LoggerFactory.getLogger(GlobalTransitionAspect.class);
    @Autowired
    private DynamicDataSource dynamicDataSource;

    /**
     * 切面點(diǎn) 指定注解
     */
    @Pointcut("@annotation(com.code2roc.fastkernel.datasource.GlobalTransactional) " +
            "|| @within(com.code2roc.fastkernel.datasource.GlobalTransactional)")
    public void dataSourcePointCut() {

    }

    /**
     * 攔截方法指定為 dataSourcePointCut
     */
    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        GlobalTransactional methodAnnotation = method.getAnnotation(GlobalTransactional.class);
        if (methodAnnotation != null) {
            DataSourceContextHolder.tagGlobal();
            logger.info("標(biāo)記全局事務(wù)");
        }
        try {
            return point.proceed();
        } finally {
            logger.info("清除全局事務(wù)");
            DataSourceContextHolder.clearGlobal();
        }
    }
}
public class DataSourceContextHolder {
    private static Logger log = LoggerFactory.getLogger(DataSourceContextHolder.class);
    // 對(duì)當(dāng)前線程的操作-線程安全的
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
    private static final ThreadLocal<String> contextGlobalHolder = new ThreadLocal<String>();

    // 調(diào)用此方法,切換數(shù)據(jù)源
    public static void setDataSource(String dataSource) {
        contextHolder.set(dataSource);
        log.debug("已切換到數(shù)據(jù)源:{}", dataSource);
    }

    // 獲取數(shù)據(jù)源
    public static String getDataSource() {
        String value = contextHolder.get();
        if (StringUtil.isEmpty(value)) {
            value = "master";
        }
        if (!StringUtil.isEmpty(getGlobal())) {
            value = value + "-xa";
        }
        return value;
    }

    // 刪除數(shù)據(jù)源
    public static void clearDataSource() {
        contextHolder.remove();
        log.debug("已切換到主數(shù)據(jù)源");
    }

    //====================全局事務(wù)標(biāo)記================
    public static void tagGlobal() {
        contextGlobalHolder.set("1");
    }

    public static String getGlobal() {
        String value = contextGlobalHolder.get();
        return value;
    }

    public static void clearGlobal() {
        contextGlobalHolder.remove();
    }
    //===================================================
}

配置XA事務(wù)日志

通過(guò)在resource文件夾下創(chuàng)建transactions.properties文件可以指定XA事務(wù)日志的存儲(chǔ)路徑

com.atomikos.icatch.log_base_dir= tempfiles/transition/

到此這篇關(guān)于SpringBoot整合atomikos實(shí)現(xiàn)跨庫(kù)事務(wù)的文章就介紹到這了,更多相關(guān)SpringBoot整合atomikos內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java實(shí)現(xiàn)圖片滑動(dòng)驗(yàn)證(包含前端代碼)

    java實(shí)現(xiàn)圖片滑動(dòng)驗(yàn)證(包含前端代碼)

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)圖片滑動(dòng)驗(yàn)證,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • Spring Boot解決項(xiàng)目啟動(dòng)時(shí)初始化資源的方法

    Spring Boot解決項(xiàng)目啟動(dòng)時(shí)初始化資源的方法

    這篇文章主要給大家介紹了關(guān)于Spring Boot如何解決項(xiàng)目啟動(dòng)時(shí)初始化資源的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05
  • Java Vector實(shí)現(xiàn)班級(jí)信息管理系統(tǒng)

    Java Vector實(shí)現(xiàn)班級(jí)信息管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Java Vector實(shí)現(xiàn)班級(jí)信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Mybatis Plus代碼生成器(時(shí)間管理大師)

    Mybatis Plus代碼生成器(時(shí)間管理大師)

    這篇文章主要介紹了Mybatis Plus代碼生成器(時(shí)間管理大師)的相關(guān)知識(shí),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Java中如何判斷中文字符串長(zhǎng)度

    Java中如何判斷中文字符串長(zhǎng)度

    這篇文章主要介紹了Java中如何判斷中文字符串長(zhǎng)度問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • 使用@EnableWebMvc輕松配置Spring MVC

    使用@EnableWebMvc輕松配置Spring MVC

    這篇文章主要為大家介紹了使用@EnableWebMvc輕松配置Spring MVC實(shí)現(xiàn)示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • 一鍵清除maven倉(cāng)庫(kù)中下載失敗的jar包的實(shí)現(xiàn)方法

    一鍵清除maven倉(cāng)庫(kù)中下載失敗的jar包的實(shí)現(xiàn)方法

    這篇文章主要介紹了一鍵清除maven倉(cāng)庫(kù)中下載失敗的jar包的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • maven的settings.xml、pom.xml配置文件使用詳解

    maven的settings.xml、pom.xml配置文件使用詳解

    本文詳解了Maven中的配置文件settings.xml和pom.xml,闡述了它們的作用、配置項(xiàng)以及優(yōu)先級(jí)順序,settings.xml存在于Maven安裝目錄和用戶目錄下,分別作用于全局和當(dāng)前用戶,pom.xml位于項(xiàng)目根路徑下
    2024-09-09
  • Spring Retry重試框架的使用講解

    Spring Retry重試框架的使用講解

    重試的使用場(chǎng)景比較多,比如調(diào)用遠(yuǎn)程服務(wù)時(shí),由于網(wǎng)絡(luò)或者服務(wù)端響應(yīng)慢導(dǎo)致調(diào)用超時(shí),此時(shí)可以多重試幾次。用定時(shí)任務(wù)也可以實(shí)現(xiàn)重試的效果,但比較麻煩,用Spring Retry的話一個(gè)注解搞定所有,感興趣的可以了解一下
    2023-01-01
  • SpringBoot中的CompletableFuture類詳解

    SpringBoot中的CompletableFuture類詳解

    這篇文章主要介紹了SpringBoot中的CompletableFuture類詳解,在?Java8中,引入了CompletableFuture類,它提供了一種簡(jiǎn)單而強(qiáng)大的方式來(lái)執(zhí)行異步任務(wù),今天我們就來(lái)詳細(xì)解讀一下這個(gè)類,需要的朋友可以參考下
    2023-07-07

最新評(píng)論

乐安县| 达拉特旗| 青龙| 古交市| 永登县| 濮阳市| 防城港市| 西盟| 海林市| 安仁县| 贵阳市| 宝坻区| 昌都县| 文化| 鲁甸县| 克拉玛依市| 喀喇沁旗| 四平市| 阜平县| 新巴尔虎左旗| 大埔区| 伊金霍洛旗| 罗源县| 金寨县| 鄂托克旗| 北川| 贺兰县| 南漳县| 清水河县| 东乡族自治县| 汾阳市| 宜君县| 理塘县| 宣汉县| 常宁市| 武功县| 朝阳市| 华亭县| 克拉玛依市| 报价| 扶风县|