SpringCloud入门(三十二) ------Seata 解决分布式事务

微服务下的分布式事务问题:

比如有三个微服务,订单服务调用库存服务,库存减少库存后,需要调用支付服务,从用户余额里减少余额。
但是如果如果库存出现问题,报错了,或者扣除余额的时候出错了,订单依然出库了,就会出现很大的问题。

什么是 Seata

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

Seata 术语

  • TC - 事务协调者: 维护全局和分支事务的状态,驱动全局事务提交或回滚。
  • TM - 事务管理器: 定义全局事务的范围:开始全局事务、提交或回滚全局事务。
  • RM - 资源管理器: 管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
  • XID - 唯一事务ID: 全局的事务标记

Seata 处理过程

  1. TM(开启分布式事务的方法) 向 TC(Seata服务端) 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID ;
  2. XID 在微服务调用链路的上下文传播 ;
  3. RM(连接数据库) 向 TC 注册分支事务,将其纳入 XID 对应全局事务的管辖;
  4. TM 向 TC 发起针对 XID 的全局提交或者回滚决议;
  5. TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求。

SpringCloud入门(三十二) ------Seata 解决分布式事务_第1张图片

搭建 Seata 的微服务

官网下载 Seata ,本次下载的是1.0版本
修改Seata conf目录下的 file.conf , registry.conf

file.conf: 采用db的方式
SpringCloud入门(三十二) ------Seata 解决分布式事务_第2张图片
SpringCloud入门(三十二) ------Seata 解决分布式事务_第3张图片
registry.conf: 采用nacos方式
SpringCloud入门(三十二) ------Seata 解决分布式事务_第4张图片

执行config目录下的 sql脚本:

在这里插入图片描述
db_store.sql:在seata连接的库执行。
db_undo_log.sql:在微服务连接的库下执行。

启动Seata,bin目录下,双击seata-server.bat
搭建微服务,新增 Seata pom依赖:
		<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>seata-all</artifactId>
                    <groupId>io.seata</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
            <version>1.0.0</version>
        </dependency>
yml:
spring:
  application:
    name: jym-seata-order
  cloud:
    alibaba:
      seata:
        tx-service-group: jym-group                      # 自定义事务组的名称需要与seata-server中的对应
    nacos:
      discovery:
        server-addr: localhost:8848
将seata 中的 file.conf , registry.conf复制到resource目录下,并修改:

因为我配置的名为 jym-group,所以mapping.后面为 jym-group
SpringCloud入门(三十二) ------Seata 解决分布式事务_第5张图片

启动类:

使用自己配置的数据源,排除mybatis默认的

@SpringBootApplication(exclude = {MybatisAutoConfiguration.class})
@EnableDiscoveryClient
@EnableFeignClients
public class SeataStorageApplication {
    public static void main(String[] args) {
        SpringApplication.run(SeataStorageApplication.class,args);
    }
}
配置数据源:
@Configuration
public class DataSourceProxyConfig {

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

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

    @Bean
    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(mapperLocations));
        sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());
        return sqlSessionFactoryBean.getObject();
    }

}
使用feign 调用微服务,业务类:
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Resource
    private OrderDao orderDao;

    @Resource
    private StorageService storageService;

    @Resource
    private AccountService accountService;

    @Override
    @GlobalTransactional(name = "jym-create-order" ,rollbackFor = Exception.class)
    public void create(Order order) {
        log.info("-----------> 开始新建订单");
        orderDao.create(order);
        log.info("-----------> 调用库存,做扣减");
        storageService.decrease(order);
        log.info("-----------> 调用余额,做扣减");
        accountService.decrease(order);
        log.info("-----------> 扣减end");
        log.info("-----------> 修改订单状态开始");
        orderDao.update(order.getUserId(),0);
        log.info("-----------> 创建订单end");
    }

}

@GlobalTransactional注解:开启全局事务

学习年限不足,知识过浅,说的不对请见谅。

世界上有10种人,一种是懂二进制的,一种是不懂二进制的。

你可能感兴趣的:(springcloud)