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基础(五)函数式接口-复用,解耦之利刃

相关推荐
笃励13 分钟前
Java面试题二
java·开发语言·python
易雪寒31 分钟前
IDEA在git提交时添加忽略文件
java·git·intellij-idea
打码人的日常分享1 小时前
企业人力资源管理,人事档案管理,绩效考核,五险一金,招聘培训,薪酬管理一体化管理系统(源码)
java·数据库·python·需求分析·规格说明书
27669582921 小时前
京东e卡滑块 分析
java·javascript·python·node.js·go·滑块·京东
爱写代码的刚子1 小时前
C++知识总结
java·开发语言·c++
冷琴19961 小时前
基于java+springboot的酒店预定网站、酒店客房管理系统
java·开发语言·spring boot
daiyang123...2 小时前
IT 行业的就业情况
java
爬山算法2 小时前
Maven(6)如何使用Maven进行项目构建?
java·maven
.生产的驴2 小时前
Electron Vue框架环境搭建 Vue3环境搭建
java·前端·vue.js·spring boot·后端·electron·ecmascript
爱学的小涛2 小时前
【NIO基础】基于 NIO 中的组件实现对文件的操作(文件编程),FileChannel 详解
java·开发语言·笔记·后端·nio