Seata 分布式事务

Posted JAVA乐园

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Seata 分布式事务相关的知识,希望对你有一定的参考价值。

0x01:什么是分布式事务

一次业务操作需要垮多个数据源或需要垮多个系统进行远程调用,就会产生分布式事务问题

Seata 分布式事务


Seata 分布式事务

一个典型的分布式事务(1+3)

分布式事务处理过程-ID+三组件模型

   Transaction ID(XID)

  • 全局唯一的事务id

三组件概念

  • Transaction Coordinator(TC)

    事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚

  • Transaction Manager(TM)

    控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议

  • Resource Manager(RM)

    控制分支事务,负责分支注册、状态汇报,并接受事务协调的指令,驱动分支(本地)事务的提交和回滚

处理过程

Seata 分布式事务


Seata 分布式事务


0x02:配置 state

一、下载seata解压 

https://github.com/seata/seata/releases

Seata 分布式事务

二、修改conf文件夹的 file.conf 文件

  • 先备份原始 file.conf 文件

  • 修改 file.conf 文件

        修改service模块,可以改为自己的工程名

Seata 分布式事务

  • store模块

      存到数据库

Seata 分布式事务


Seata 分布式事务

三、在数据库建库和建表(配置文件有)

  • mysql5.7 数据库新建库 seata

  • 建表 db_store.sql 在 seata-server-0.9.0\seata\conf 目录里面 db_store.sql

四、修改 seata-server-0.9.0\seata\conf 目录下的 registry.conf 目录下的 registry.conf 配置文件

Seata 分布式事务

五、启动nacos  seata-server

Seata 分布式事务

Seata 分布式事务



0x03:实例准备 订单 库存 账户

Seata 分布式事务

一、数据库准备

Seata 分布式事务

create database seata_order;

create database seata_storage;

create database seata_account;

Seata 分布式事务

DROP TABLE IF EXISTS `t_order`;
CREATE TABLE `t_order`  (
  `int` bigint(11NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20DEFAULT NULL COMMENT '用户id',
  `product_id` bigint(11DEFAULT NULL COMMENT '产品id',
  `count` int(11DEFAULT NULL COMMENT '数量',
  `money` decimal(110DEFAULT NULL COMMENT '金额',
  `status` int(1DEFAULT NULL COMMENT '订单状态:  0:创建中 1:已完结',
  PRIMARY KEY (`int`USING BTREE
ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '订单表' ROW_FORMAT = Dynamic;

DROP TABLE IF EXISTS `t_storage`;
CREATE TABLE `t_storage`  (
  `int` bigint(11NOT NULL AUTO_INCREMENT,
  `product_id` bigint(11DEFAULT NULL COMMENT '产品id',
  `total` int(11DEFAULT NULL COMMENT '总库存',
  `used` int(11DEFAULT NULL COMMENT '已用库存',
  `residue` int(11DEFAULT NULL COMMENT '剩余库存',
  PRIMARY KEY (`int`USING BTREE
ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '库存' ROW_FORMAT = Dynamic;
INSERT INTO `t_storage` VALUES (111000100);

CREATE TABLE `t_account`  (
  `id` bigint(11NOT NULL COMMENT 'id',
  `user_id` bigint(11DEFAULT NULL COMMENT '用户id',
  `total` decimal(100DEFAULT NULL COMMENT '总额度',
  `used` decimal(100DEFAULT NULL COMMENT '已用余额',
  `residue` decimal(100DEFAULT NULL COMMENT '剩余可用额度',
  PRIMARY KEY (`id`USING BTREE
ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '账户表' ROW_FORMAT = Dynamic;
INSERT INTO `t_account` VALUES (11100001000);

建立滚日志表

  • 订单-库存-账户3个库下都需要建各自独立的回滚日志表

       seata-server-0.9.0\seata\conf\目录下的db_undo_log.sql

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

Seata 分布式事务

二、微服务准备

Seata 分布式事务

新建订单模块举例

  • pom

<dependencies>
            <!-- nacos -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
            <!-- nacos -->

            <!-- seata-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>io.seata</groupId>
                        <artifactId>seata-all</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>io.seata</groupId>
                <artifactId>seata-all</artifactId>
                <version>0.9.0</version>
            </dependency>
            <!-- seata-->
            <!--feign-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <!--jdbc-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
  • yml文件

yml文件的 tx-service-group需要和配置文件的对应

Seata 分布式事务

server:
  port: 2001

spring:
  application:
    name: seata-order-service
  cloud:
    alibaba:
      seata:
        # 自定义事务组名称需要与seata-server中的对应
        tx-service-group: fsp_tx_group
    nacos:
      discovery:
        server-addr: localhost:8848
  datasource:
    # 当前数据源操作类型
    type: com.alibaba.druid.pool.DruidDataSource
    # mysql驱动类
    driver-class-namecom.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
    username: root
    password: root
feign:
  hystrix:
    enabled: false
logging:
  level:
    io:
      seata: info

mybatis:
  mapper-locations: classpath:mapper/*.xml
  •  在 resource 目录下新建 file.conf  registry.conf

    拷贝seata-server/conf目录下的file.conf

    拷贝seata-server/conf目录下的registry.conf

Seata 分布式事务

  • 写实体类  写 dao 接口 实现类  xml等

配置文件(注意)

/**
 * 使用Seata对数据源进行代理
 */

@Configuration
public class DataSourceProxyConfig {

    @Value("${mybatis.mapperLocations}")
    private String mapperLocations;

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

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

    @Bean
    public SqlSessionFactory sqlSessionFactoryBean(DataSourceProxy dataSourceProxy) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSourceProxy);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
        sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());
        return sqlSessionFactoryBean.getObject();
    }

}

@Configuration
@MapperScan({"com.atguigu.springcloud.alibaba.dao"})
public class MyBatisConfig {
}

启动类 (注意)

@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)//取消数据源的自动创建
public class SeataOrderMainApp2001
{

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


0x04:@GlobalTransactional注解详解

  • 直接在业务逻辑的方法上加上这个注解就行了 

  • 就可以达到分布式微服务的事务管理


0x05:state 原理详解

Seata 分布式事务

分布式事务执行流程

Seata 分布式事务

seata的几个模式

Seata 分布式事务

AT模式对业务无侵入(几个阶段)

一阶段加载

Seata 分布式事务

Seata 分布式事务

二阶段提交

Seata 分布式事务

三阶段回滚

Seata 分布式事务

喜欢,在看


以上是关于Seata 分布式事务的主要内容,如果未能解决你的问题,请参考以下文章

Seata TCC 分布式事务

SpringCloud-2.0-周阳(24. 分布式事务 - Seata)

Seata分布式事务源码分析

Spring Cloud Alibaba Seata 分布式事务使用快速入门,Nacos做Seata的注册中心和配置中心

Spring Cloud Alibaba Seata 分布式事务使用快速入门,Nacos做Seata的注册中心和配置中心

Spring Cloud Alibaba Seata 分布式事务使用快速入门,Nacos做Seata的注册中心和配置中心