欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中seata框架的XA模式詳解

 更新時間:2023年08月30日 08:45:30   作者:等後那場雪  
這篇文章主要介紹了Java中seata框架的XA模式詳解,Seata?是一款開源的分布式事務解決方案,致力于提供高性能和簡單易用的分布式事務服務,Seata?將為用戶提供了?AT、TCC、SAGA?和?XA?事務模式,為用戶打造一站式的分布式解決方案,需要的朋友可以參考下

XA模式

XA 模式屬于一種強一致性的事務模式。

前提

支持 XA 模式的數(shù)據(jù)庫。

Java 應用通過 JDBC 訪問數(shù)據(jù)庫。

整體機制

在 Seata 定義的分布式事務框架內(nèi),利用事務資源(數(shù)據(jù)庫、消息服務等)對 XA 協(xié)議提供可回滾、持久化的支持,使用 XA 協(xié)議的機制來管理分支事務。

img

執(zhí)行階段

執(zhí)行 XA Start、業(yè)務 SQL、XA End =》注冊分支,XA Prepare => 報告分支事務的狀態(tài)。

完成階段

執(zhí)行 XA Commit / XA Rollback 操作進行分支事務的提交或者回滾。

XA 模式需要 XAConnection,而獲取 XAConnection 的方式有兩種:

  • 方式一、要求開發(fā)者配置 XADataSource。給開發(fā)者增加了認知負擔,需要為 XA 模式專門去學習和使用 XA 數(shù)據(jù)源,與透明化 XA 編程模型的設計目標相悖。
  • 方式二、根據(jù)開發(fā)者的普通 DataSource 來創(chuàng)建。對開發(fā)者比較友好,和 AT 模式一樣,開發(fā)者完全不需要關心 XA 層面的任何問題,保持本地編程模型即可。

優(yōu)先設計實現(xiàn)第二種方式,數(shù)據(jù)源代理根據(jù)普通數(shù)據(jù)源中獲取的普通 JDBC 連接創(chuàng)建出相應的 XAConnection。

類比 AT 模式的數(shù)據(jù)源代理機制,如下:

ds1

但是,第二種方法有局限:無法保證兼容的正確性。

實際上,這種方法是在做數(shù)據(jù)庫驅(qū)動程序要做的事情。不同的廠商、不同版本的數(shù)據(jù)庫驅(qū)動實現(xiàn)機制是廠商私有的,我們只能保證在充分測試過的驅(qū)動程序上是正確的,開發(fā)者使用的驅(qū)動程序版本差異很可能造成機制的失效。

綜合考慮,XA 模式的數(shù)據(jù)源代理設計需要同時支持第一種方式:基于 XA 數(shù)據(jù)源進行代理。

類比 AT 模式的數(shù)據(jù)源代理機制,如下:

ds2

使用方法

每個服務的 file.conf、registry.conf 配置文件的配置這里先不提供。

Business服務
|
|------> Stock服務
|
|------> Order服務 -----> Account服務

Business服務

BusinessService

@GlobalTransactional
public void purchase(String userId, String commodityCode, int orderCount, boolean rollback) {
    String xid = RootContext.getXID();
    LOGGER.info("New Transaction Begins: " + xid);
    String result = stockFeignClient.deduct(commodityCode, orderCount);
    if (!SUCCESS.equals(result)) {
        throw new RuntimeException("庫存服務調(diào)用失敗,事務回滾!");
    }
    result = orderFeignClient.create(userId, commodityCode, orderCount);
    if (!SUCCESS.equals(result)) {
        throw new RuntimeException("訂單服務調(diào)用失敗,事務回滾!");
    }
    if (rollback) {
        throw new RuntimeException("Force rollback ... ");
    }
}

BusinessXADataSourceConfiguration

@Configuration
public class BusinessXADataSourceConfiguration {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidDataSource dataSource() {
        return new DruidDataSource();
    }
}

Stock服務

StockBusiness

public void deduct(String commodityCode, int count) {
    String xid = RootContext.getXID();
    LOGGER.info("deduct stock balance in transaction: " + xid);
    jdbcTemplate.update("update seata_stock set count = count - ? where commodity_code = ?",
        new Object[] {count, commodityCode});
}

application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://10.211.55.6:3306/seata_stock?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=root

StockXADataSourceConfiguration

@Configuration
public class StockXADataSourceConfiguration {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidDataSource druidDataSource() {
        return new DruidDataSource();
    }
    @Bean("dataSourceProxy")
    public DataSource dataSource(DruidDataSource druidDataSource) {
        return new DataSourceProxyXA(druidDataSource);
    }
    @Bean("jdbcTemplate")
    public JdbcTemplate jdbcTemplate(DataSource dataSourceProxy) {
        return new JdbcTemplate(dataSourceProxy);
    }
}

Order服務

OrderService

public void create(String userId, String commodityCode, Integer count) {
    String xid = RootContext.getXID();
    LOGGER.info("create order in transaction: " + xid);
    // 定單總價 = 訂購數(shù)量(count) * 商品單價(100)
    int orderMoney = count * 100;
    // 生成訂單
    jdbcTemplate.update("insert seata_order(user_id,commodity_code,count,money) values(?,?,?,?)",
        new Object[] {userId, commodityCode, count, orderMoney});
    // 調(diào)用賬戶余額扣減
    String result = accountFeignClient.reduce(userId, orderMoney);
    if (!SUCCESS.equals(result)) {
        throw new RuntimeException("Failed to call Account Service. ");
    }
}

application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://10.211.55.6:3306/seata_order?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=root

OrderXADataSourceConfiguration

@Configuration
public class OrderXADataSourceConfiguration {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidDataSource druidDataSource() {
        return new DruidDataSource();
    }
    @Bean("dataSourceProxy")
    public DataSource dataSource(DruidDataSource druidDataSource) {
        return new DataSourceProxyXA(druidDataSource);
    }
    @Bean("jdbcTemplate")
    public JdbcTemplate jdbcTemplate(DataSource dataSourceProxy) {
        return new JdbcTemplate(dataSourceProxy);
    }
}

Account服務

AccountService

@Transactional
public void reduce(String userId, int money) {
    String xid = RootContext.getXID();
    LOGGER.info("reduce account balance in transaction: " + xid);
    jdbcTemplate.update("update seata_account set money = money - ? where user_id = ?", new Object[] {money, userId});
    int balance = jdbcTemplate.queryForObject("select money from seata_account where user_id = ?",
        new Object[] {userId}, Integer.class);
    LOGGER.info("balance after transaction: " + balance);
    if (balance < 0) {
        throw new RuntimeException("Not Enough Money ...");
    }
}

application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://10.211.55.6:3306/seata_account?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=root

AccountXADataSourceConfiguration

@Configuration
public class AccountXADataSourceConfiguration {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidDataSource druidDataSource() {
        return new DruidDataSource();
    }
    @Bean("dataSourceProxy")
    public DataSource dataSource(DruidDataSource druidDataSource) {
        return new DataSourceProxyXA(druidDataSource);
    }
    @Bean("jdbcTemplate")
    public JdbcTemplate jdbcTemplate(DataSource dataSourceProxy) {
        return new JdbcTemplate(dataSourceProxy);
    }
    @Bean
    public PlatformTransactionManager txManager(DataSource dataSourceProxy) {
        return new DataSourceTransactionManager(dataSourceProxy);
    }
}

啟動類需要標注 @EnableTransactionManagement 注解。

到此這篇關于Java中seata框架的XA模式詳解的文章就介紹到這了,更多相關seata框架的XA模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java 讀寫Properties配置文件詳解

    Java 讀寫Properties配置文件詳解

    這篇文章主要介紹了Java 讀寫Properties配置文件詳解的相關資料,這里舉例說明該如何實現(xiàn),具有參考價值,需要的朋友可以參考下
    2016-11-11
  • Netty分布式pipeline管道異常傳播事件源碼解析

    Netty分布式pipeline管道異常傳播事件源碼解析

    這篇文章主要為大家介紹了Netty分布式pipeline管道異常傳播事件源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-03-03
  • Java使用poi獲取不到docx表格中書簽的問題及解決

    Java使用poi獲取不到docx表格中書簽的問題及解決

    這篇文章主要介紹了Java使用poi獲取不到docx表格中書簽的問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • 詳解Java數(shù)組的定義和聲明方法

    詳解Java數(shù)組的定義和聲明方法

    在Java開發(fā)中,數(shù)組是最常用的數(shù)據(jù)結(jié)構(gòu)之一,因此,深入了解Java數(shù)組的定義和聲明是非常必要的,本文將詳細介紹Java數(shù)組的定義和聲明方法,以及其在實際開發(fā)中的應用場景、優(yōu)缺點等方面,需要的朋友可以參考下
    2023-11-11
  • Struts2開發(fā)環(huán)境搭建 附簡單登錄功能實例

    Struts2開發(fā)環(huán)境搭建 附簡單登錄功能實例

    這篇文章主要介紹了Struts2開發(fā)環(huán)境搭建,為大家分享一個簡單登錄功能實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • MyBatisPlus 自定義sql語句的實現(xiàn)

    MyBatisPlus 自定義sql語句的實現(xiàn)

    這篇文章主要介紹了MyBatisPlus 自定義sql語句的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-08-08
  • Java和SQL實現(xiàn)取兩個字符間的值

    Java和SQL實現(xiàn)取兩個字符間的值

    這篇文章主要介紹了Java和SQL實現(xiàn)取兩個字符間的值操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 利用idea搭建SSM項目看這一篇就夠了

    利用idea搭建SSM項目看這一篇就夠了

    SSM(Spring+SpringMVC+MyBatis)框架集由Spring、MyBatis兩個開源框架整合而成(SpringMVC是Spring中的部分內(nèi)容),常作為數(shù)據(jù)源較簡單的web項目的框架,下面這篇文章主要給大家介紹了關于利用idea搭建SSM項目的相關資料,需要的朋友可以參考下
    2023-05-05
  • Java如何設置PDF文檔背景色詳解

    Java如何設置PDF文檔背景色詳解

    這篇文章主要介紹了Java如何設置PDF文檔背景色詳解,一般生成的PDF文檔默認的文檔底色為白色,我們可以通過一定方法來更改文檔的背景色,以達到文檔美化以及保護雙眼的作用。 以下內(nèi)容提供了Java編程來設置PDF背景色的方法,需要的朋友可以參考下
    2019-07-07
  • Java將Word轉(zhuǎn)換成PDF的常用用法

    Java將Word轉(zhuǎn)換成PDF的常用用法

    Java開發(fā)人員在處理文檔轉(zhuǎn)換時,常常需要將Word或Excel文檔轉(zhuǎn)換為PDF格式,以便于更好地保持格式一致性、便于分發(fā)和打印,這篇文章主要給大家介紹了關于Java將Word轉(zhuǎn)換成PDF的常用用法,需要的朋友可以參考下
    2024-08-08

最新評論