Seata源码(十九)AT和XA模式例子


铿然架构 | 作者 / 铿然一叶 这是 铿然架构 的第 109 篇原创文章


1. 安装Server

1.下载软件 github.com/seata/seata...

2.本地目录解压 D:\MyApp\seata\seataserver1.7.1

3.启动server seata-server.bat

注意:配置文件在D:\MyApp\seata\seataserver1.7.1\conf\application.yml,默认使用文件方式,不需要修改

2. 运行Demo

2.1 克隆代码到本地

github.com/seata/seata...

demo架构图:

2.2 打开Seata-xa的例子

注:XA和AT模式的demo是同一个,只需要修改下使用的数据库代理类。

2.3 创建数据库和用户

该例子只使用一个数据库。

sql 复制代码
CREATE DATABASE businessdb;
create user business@'%' IDENTIFIED BY 'business123';
GRANT ALL PRIVILEGES ON businessdb.* TO business@'%';

2.4 创建表

执行业务脚本:

AT模式undo log脚本:

r 复制代码
CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

2.5 修改数据库配置

修改每个module的数据库配置

2.6 修改代码使用AT模式

修改module下的xxxxxDataSourceConfiguration文件

2.7 启动各个module

注:每次启动bussiness-xa module都会初始化数据库里的数据。

3. 测试

发送HTTP请求:

http://127.0.0.1:8084/purchase?rollback=false&count=1

通过浏览器,curl命令,postman都可以。

参数说明:

参数 说明
rollback 是否回退,如果回退,代码中抛出异常触发回退操作
count 订单数量,扣减库存,如果不传入,默认每次是30

初始化库存总量为:100,账户余额为:1000。

3.1 测试场景

3.1.1 正常测试

订购数量小于库存,账户余额足够:

http://127.0.0.1:8084/purchase?rollback=false&count=1

3.1.2 账户余额不足

订购数量大于库存,所需购买金额大于账户余额:

http://127.0.0.1:8084/purchase?rollback=false&count=10000

3.1.3 手动触发回退

设置rollback为true:

http://127.0.0.1:8084/purchase?rollback=true&count=1

3.2 AT模式支持

1.添加maven依赖:

xml 复制代码
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-seata</artifactId>
                <version>2.0.0.RELEASE</version>
                <exclusions>
                    <exclusion>
                        <groupId>io.seata</groupId>
                        <artifactId>seata-all</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>io.seata</groupId>
                <artifactId>seata-all</artifactId>
                <version>${seata.version}</version>
            </dependency>

2.业务入口增加GlobalTransactional注解

注:GlobalTransactional可加在类上或者方法上

typescript 复制代码
// BusinessService.java
    @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("库存服务调用失败,事务回滚!");
        }

        result = orderFeignClient.create(userId, commodityCode, orderCount);

        if (!SUCCESS.equals(result)) {
            throw new RuntimeException("订单服务调用失败,事务回滚!");
        }

        if (rollback) {
            throw new RuntimeException("Force rollback ... ");
        }
    }

3.使用DataSourceProxy

kotlin 复制代码
package io.seata.sample;

import javax.sql.DataSource;

import com.alibaba.druid.pool.DruidDataSource;

import io.seata.rm.datasource.DataSourceProxy;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

@Configuration
public class BusinessXADataSourceConfiguration {

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

    @Bean("dataSourceProxy")
    public DataSource dataSource(DruidDataSource druidDataSource) {
        // DataSourceProxy for AT mode
        return new DataSourceProxy(druidDataSource);

        // DataSourceProxyXA for XA mode
//        return new DataSourceProxyXA(druidDataSource);
    }

    @Bean("jdbcTemplate")
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

其他阅读:

萌新快速成长之路
如何编写软件设计文档
JAVA编程思想(一)通过依赖注入增加扩展性
JAVA编程思想(二)如何面向接口编程
JAVA编程思想(三)去掉别扭的if,自注册策略模式优雅满足开闭原则
JAVA编程思想(四)Builder模式经典范式以及和工厂模式如何选?
Java编程思想(七)使用组合和继承的场景
JAVA基础(一)简单、透彻理解内部类和静态内部类
JAVA基础(二)内存优化-使用Java引用做缓存
JAVA基础(三)ClassLoader实现热加载
JAVA基础(四)枚举(enum)和常量定义,工厂类使用对比
JAVA基础(五)函数式接口-复用,解耦之利刃

相关推荐
计算机学姐几秒前
基于SpringBoot的奶茶店点餐系统【协同过滤推荐算法+数据可视化统计】
java·vue.js·spring boot·mysql·信息可视化·tomcat·推荐算法
@土豆4 分钟前
Java JVM参数环境变量详解及SkyWalking Agent集成技术文档
java·jvm·skywalking
Yupureki5 分钟前
《Linux系统编程》19.线程同步与互斥
java·linux·服务器·c语言·开发语言·数据结构·c++
又来敲代码了6 分钟前
Zrlog博客的系统部署
java·linux·运维·mysql·apache·tornado
砍光二叉树6 分钟前
【设计模式】行为型-责任链模式
java·设计模式·责任链模式
kiki_241116 分钟前
用IntelliJ IDEA编写Java程序,从0到1完整教程
java·ide·intellij-idea
liuyao_xianhui18 分钟前
优选算法_锯齿形层序遍历二叉树_队列_C++
java·开发语言·数据结构·c++·算法·链表
八宝粥大朋友19 分钟前
Android sqlite3 编译及安装
android·java·sqlite
wxm63122 分钟前
TCP监听--监听指定IP的端口号
java·网络·tcp/ip
csdn2015_33 分钟前
java 把对象转化为json字符串
java·前端·json