关于springcloud:架构设计-基于Seata中间件微服务模式下事务管理

4次阅读

共计 4327 个字符,预计需要花费 11 分钟才能阅读完成。

源码地址:GitHub·点这里 || GitEE·点这里

一、Seata 简介

1、Seata 组件

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简略易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA、XA 事务模式,为用户打造一站式的分布式解决方案。

2、反对模式

AT 模式

  • 基于反对本地 ACID 事务的关系型数据库。
  • Java 利用,通过 JDBC 拜访数据库。

一阶段:业务数据和回滚日志记录在同一个本地事务中提交,开释本地锁和连贯资源。

二阶段:提交异步化,十分疾速地实现。回滚通过一阶段的回滚日志进行反向弥补。

TCC 模式

一个分布式的全局事务,整体是两阶段提交的模型,全局事务是由若干分支事务组成的,分支事务要满足两阶段提交的模型要求,即须要每个分支事务都具备本人的:

一阶段 prepare 行为

二阶段 commit 或 rollback 行为

Saga 模式

Saga 模式是 SEATA 提供的长事务解决方案,在 Saga 模式中,业务流程中每个参与者都提交本地事务,当呈现某一个参与者失败则弥补后面曾经胜利的参与者,一阶段正向服务和二阶段弥补服务都由业务开发实现。

XA 模式

XA 是一个分布式事务协定,对业务无侵入的分布式事务解决方案,XA 提交协定须要事务参与者的数据库反对,XA 事务具备强一致性,在两阶段提交的整个过程中,始终会持有资源的锁,性能不现实的毛病很显著。

二、服务端部署

1、下载组件包

1.2 版本:seata-server-1.2.0.zip

解压目录

  • bin:寄存服务端运行启动脚本;
  • lib:寄存服务端依赖的资源 jar 包;
  • conf:配置文件目录。

2、批改配置

file.conf 配置

mode:db 即应用数据库存储事务信息,这里还能够抉择 file 存储形式。

file 模式为单机模式,全局事务会话信息内存中读写并长久化本地文件 root.data,性能较高;

db 模式为高可用模式,全局事务会话信息通过 db 共享,相应性能差些;

redis 模式 Seata-Server 1.3 及以上版本反对, 性能较高, 存在事务信息失落危险, 请提前配置适合以后场景的 redis 长久化配置.

store {
  ## store mode: file、db
  mode = "db"
  db {
    datasource = "druid"
    dbType = "mysql"
    driverClassName = "com.mysql.jdbc.Driver"
    url = "jdbc:mysql://127.0.0.1:3306/seata_server"
    user = "root"
    password = "123456"
    minConn = 5
    maxConn = 30
    globalTable = "global_table"
    branchTable = "branch_table"
    lockTable = "lock_table"
    queryLimit = 100
    maxWait = 5000
  }
}

registry.conf 配置

这里抉择 eureka 作为注册核心,seata-server 也要作为一个服务增加到注册核心,不应用配置核心所以 config 配置默认即可。

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

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

3、事务管理表

须要在 seata-server 即上述配置的 MySQL 库中建设 3 张事务管理表:

  • 全局事务:global_table
  • 分支事务:branch_table
  • 全局锁:lock_table
  • 事务回滚:undo_log
  • SQL 脚本:mysql-script 目录

4、启动命令

Linux 环境:sh seata-server.sh

三、业务服务搭建

1、代码构造

  • seata-eureka:注册核心
  • seata-order:订单服务
  • seata-account:账户服务
  • seata-inventor:库存服务
  • seata-client:客户端服务
  • account-feign:账户 Feign 接口
  • inventory-feign:库存 Feign 接口
  • order-feign:订单 Feign 接口

申请链路 :客户端 -> 订单 -> 账户 + 库存,测试整个流程的分布式事务问题。

2、数据库构造

  • seata_server:seata 组件服务端依赖库
  • seata_account:模仿账户数据库
  • seata_inventor:模仿库存数据库
  • seata_order:模仿订单数据库

各个库脚本地位:mysql-script/data-biz.sql

3、启动服务

顺次启动:注册核心,库存服务,账户服务,订单服务,客户端服务;

Eureka 服务列表如下:

四、Seata 用法详解

1、Seata 根底配置

几个根底服务的配置形式一样。

conf 配置

file.conf 重点关注上面内容,事务组的名称,须要在 yml 文件中应用。

my_test_tx_group = "default"

registry.conf:是注册核心的抉择。

2、数据库配置

留神这里的事务组名称配置。

spring:
  # 事务组的名称
  cloud:
    alibaba:
      seata:
        tx-service-group: my_test_tx_group
  # 数据源配置
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      driverClassName: com.mysql.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/seata_account
      username: root
      password: 123456

将数据库整体由 Seata 进行代理治理,外围 API:DataSourceProxy。

@Configuration
public class SeataAccountConfig {@Value("${spring.application.name}")
    private String applicationName;

    @Bean
    public GlobalTransactionScanner globalTransactionScanner() {return new GlobalTransactionScanner(applicationName, "test-tx-group");
    }

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

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

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSourceProxy dataSourceProxy)throws Exception{SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSourceProxy);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath*:/mapper/*.xml"));
        sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());
        return sqlSessionFactoryBean.getObject();}
}

3、业务代码

外围注解:GlobalTransactional,治理整体的分布式事务。

@Service
public class OrderServiceImpl implements OrderService {private final Logger LOGGER = LoggerFactory.getLogger(OrderServiceImpl.class);

    @Resource
    private OrderMapper orderMapper ;
    @Resource
    private AccountFeign accountFeign ;
    @Resource
    private InventoryFeign inventoryFeign ;

    @GlobalTransactional
    @Override
    public Integer createOrder(String orderNo) {LOGGER.info("Order 生成中"+orderNo);
        // 本服务下订单库
        Integer insertFlag = orderMapper.insert(orderNo) ;
        // 基于 feign 接口解决账户和库存
        accountFeign.updateAccount(10L) ;
        inventoryFeign.updateInventory(10) ;
        return insertFlag ;
    }
}

测试流程:在任意服务下抛出异样,察看整体的事务状态,察看是否有整体的事务管制成果。

五、源代码地址

GitHub 地址:知了一笑
https://github.com/cicadasmile/spring-cloud-base
GitEE 地址:知了一笑
https://gitee.com/cicadasmile/spring-cloud-base

举荐浏览:架构设计系列

题目
架构设计:单服务. 集群. 分布式,根本区别和分割
架构设计:分布式业务零碎中,全局 ID 生成策略
架构设计:分布式系统调度,Zookeeper 集群化治理
架构设计:接口幂等性准则,防反复提交 Token 治理
架构设计:缓存管理模式,监控和内存回收策略
架构设计:异步解决流程,多种实现模式详解
架构设计:高并发流量削峰,共享资源加锁机制
架构设计:分布式服务,库表拆分模式详解
架构设计:分布式事务①概念简介和基础理论
架构设计:基于电商交易流程,图解 TCC 事务分段提交
架构设计:基于消息中间件,图解柔性事务一致性
正文完
 0