Seata AT分布式事物实现(三)

1. Seata Server - TC全局事务协调器

分布式事物中:
TM,RM是嵌入在业务应用中,而TC则是一个单独的服务: Seata Server
下载地址: https://github.com/seata/seata/releases

1.1 Seata Server配置文件

1. seata/conf/registry.conf
配置注册中心,那么其他服务就可以通过注册中心去发现 Seata Server,与 Seata Server 进行通信

registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  # 这里选择 eureka 注册配置
  type = "eureka"

  nacos {
	......
  }

  # eureka的注册配置
  eureka {
    # 注册中心地址
    serviceUrl = "http://localhost:8761/eureka"
    # 注册的服务ID
    application = "seata-server"
    weight = "1"
  }
  
  redis {
	......
  }
  ......

2. seata/conf/file.conf

  1. Seata 需要存储全局事务信息、分支事务信息、全局锁信息,这些数据进行存储
  2. 针对存储位置的配置,支持放在配置中心,或者也可以放在本地文件。Seata Server 支持的配置中心服务有:nacos 、apollo、zk、consul、etcd3
  3. 这里使用本地存储,
    先在registry.conf配置储存位置
......

config {
  # file、nacos 、apollo、zk、consul、etcd3
  # 在这里选择使用本地文件来保存配置
  type = "file"

......

  
  file {
    # 在这里设置配置文件的文件名
    name = "file.conf"
  }
}

file.config储存位置可存放在file、db、redis中,这里使用存放在数据库中

store {
  ## store mode: file、db、redis
  # 这里选择数据库存储
  mode = "db"
......

  # 数据库存储
  db {
    ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
    datasource = "druid"
    ## mysql/oracle/postgresql/h2/oceanbase etc.
    dbType = "mysql"
    driverClassName = "com.mysql.jdbc.Driver"

	# 数据库连接配置
    url = "jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8"
    user = "root"
    password = "root"
    minConn = 5
    maxConn = 30

	# 事务日志表表名设置
    globalTable = "global_table"
    branchTable = "branch_table"
    lockTable = "lock_table"

    queryLimit = 100
    maxWait = 5000
  }

  	......
  
}

1.2 启动Seata Server服务

1. 测试环境修改 /seata/bin/seata-server.bat文件内容(JVM参数)
用文本编辑器打开

%JAVACMD% %JAVA_OPTS% -server -Xmx2048m -Xms2048m -Xmn1024m -Xss512k -XX:Sur......

我们可以把内存调低

%JAVACMD% %JAVA_OPTS% -server -Xmx256m -Xms256m -Xmn128m -Xss512k -XX:Sur......

如果在Linux环境下, 则需要修改 /seata/bin/seata-server.sh文件参数
2. 启动Seata服务
双击seata-server.bat文件启动,检查eureka注册中心Seata的注册信息
如果在linux系统下,需要cd到文件目录下, 通过一下方式启动

sh seata-server.sh

2. 订单模块order

2.1 添加Seata依赖

或者父级项目

        <dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-alibaba-seata</artifactId>
          <version>2.0.0.RELEASE</version>
          <exclusions>
            <exclusion>
              <artifactId>seata-all</artifactId>
              <groupId>io.seata</groupId>
            </exclusion>
          </exclusions>
        </dependency>
        <dependency>
          <groupId>io.seata</groupId>
          <artifactId>seata-all</artifactId>
          <version>1.3.0</version>
        </dependency>

2.2 配置

2.2.1 application.yml

添加向seata注册, 并将当前服务加入一个事物组(要求订单,库存,账户服务所属同一组)

spring:
  cloud:
    alibaba:
      seata:
        tx-service-group: order_tx_group

2.2.2 在resource目录下添加registry.conf

需要从注册中心获得 TC 的地址,这里配置注册中心的地址。

registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "eureka"

......

  eureka {
    serviceUrl = "http://localhost:8761/eureka"
    # application = "default"
    # weight = "1"
  }
......
}  

2.2.3 在resource目录下添加file.conf

TC 在注册中心注册的服务ID在下面 file.conf 中指定。
在这里我们指定 TC 的服务ID seata-server:vgroupMapping.order_tx_group = “seata-server”
order_tx_group 对应 application.yml 中注册的事务组名。


......

service {
  #transaction service group mapping
  # order_tx_group 与 yml 中的 “tx-service-group: order_tx_group” 配置一致
  # “seata-server” 与 TC 服务器的注册名一致
  # 从eureka获取seata-server的地址,再向seata-server注册自己,设置group
  vgroupMapping.order_tx_group = "seata-server"
  #only support when registry.type=file, please don't set multiple addresses
  order_tx_group.grouplist = "127.0.0.1:8091"
  #degrade, current not support
  enableDegrade = false
  #disable seata
  disableGlobalTransaction = false
}

......

2.3 创建Seata数据源代理

Seata AT 事务对业务代码无侵入,全自动化处理全局事务,其功能是靠 Seata 的数据源代理工具实现的。
创建 Seata 的数据源代理,并排除 Spring 默认的数据源。

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

    @Primary
    @Bean("dataSource")
    public DataSourceProxy dataSource(DataSource druidDataSource){
        return new DataSourceProxy(druidDataSource);
    }
}

主程序排除springboot默认数据源

@EnableFeignClients
@MapperScan("cn.tedu.order.mapper")
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }

}

注意: seata数据源代理,数据库连接名为jdbcUrl
需要在application.yml文件中重写配置数据库连接地址

spring:
  application:
    name: storage
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/seata_storage?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
    jdbcUrl: jdbc:mysql://localhost:3306/seata_storage?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
    username: root
    password: root

2.4 启动全局事物

Seata对象业务无入侵, 所以开启全局事物很简单只需要添加一个@GlobalTransactional 注解即可
注意: 本地分支事物也是在这里开启添加@Transactional

@Service
public class OrderServiceImpl implements OrderService{
	
	@Transactional  //控制本地事物
    @GlobalTransactional //开启全局事物,只在第一个模块添加
    @Override
    //创建订单方法
    public void create(Order order) {
......

创建订单方法: 调用orderMapper实现订单数据存储,远程调用库存,账户,实现入库操作

3. 库存模块storage

3.1 添加依赖

如果父级项目添加这里不用添加

3.2 配置

3.2.1 application.yml

与订单order业务一致

3.2.2 registry.conf , file.conf

与订单order业务一致

3.3 创建Seata数据源对象

与订单order业务一致

3.4 启动分支事物

在业务方法上添加@Transactional 注解启动本地分支事务

@Service
public class StorageServiceImpl implements StorageService {
    @Autowired
    private StorageMapper storageMapper;

    @Transactional
    @Override
    public void decrease(Long productId, Integer count) throws Exception {
        storageMapper.decrease(productId,count);
    }
}

4. 账户模块

与库存模块一致

5. 启动三个服务测试

按顺序启动项目:
Eureka
Seata Server
Easy Id Generator
Storage
Account
Order

调用保存订单,地址:
http://localhost:8083/create?userId=1&productId=1&count=10&money=100

观察三个服务,查看控制台
可以观察到全局事物id(XID),和本地事物id(Branch ID)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值