Spring Cloud Alibaba整合seata 1.4.0 (二)

本文介绍了如何在SpringCloudAlibaba项目中整合Seata1.4.0,以解决分布式环境中跨服务的数据一致性问题。通过创建provider-service项目,修改my-service项目,并配置Seata,实现了全局事务管理。主要步骤包括:创建服务,配置数据源代理,添加@GlobalTransactional注解,以及在各服务数据库中创建undo_log表。
摘要由CSDN通过智能技术生成

 

步骤一、创建provider-service项目

步骤二、修改my-service项目

步骤三、创建undo_log表


Spring Cloud Alibaba整合seata 1.4.0(一)中整合了seata,但是项目中并没有使用到seata的功能,这篇博客介绍项目中如何使用seata。

使用seata是极其简单的,配置确实极其复杂的。

项目背景:

my-service中调用provider-service,调用provider-service后my-service中出现了RuntimeException或者超时异常。如果使用传统的@Transactional注解,只能保证my-service中所作的修改被回滚,不能保证provider-service中所作的修改,导致数据不一致。这时候就需要使用seata来代理数据源来控制分布式事务,从而保证数据一致性。

注意:provider-service和my-service使用不同的数据库。

伪代码

MyService{

    function(){
        changeDB();

        provider-service.changeDB();

        // 下面的代码逻辑出现了运行时异常或者超时异常
        doSomething...
        
    }
    
}

 

Spring Cloud Alibaba整合seata 1.4.0(一)的基础上作出如下配置和编码。

步骤一、创建provider-service项目

provider-service的项目创建和my-service的创建基本一致。

添加依赖、引入file.conf、引入registry.conf不再赘述

需要特别注意的几点:

1、file.conf文件中修改

service {
  #transaction service group mapping
  vgroupMapping.provider-service-group = "default"
  #only support when registry.type=file, please don't set multiple addresses
  default.grouplist = "127.0.0.1:8091"
  #degrade, current not support
  enableDegrade = false
  #disable seata
  disableGlobalTransaction = false
}

跟my-service中的配置类似

2、修改config.txt文件

在seata-server-1.4.0\seata目录下的config.txt中添加如下配置:

service.vgroupMapping.my-service-group=default
service.vgroupMapping.provider-service-group=default
 

并且将config.txt中的配置添加到nacos配置管理(上一篇文章步骤四有说明)

seata/conf目录下打开git bash执行如下命令

sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t cadb1d46-f1fa-417f-bcc7-504822fd55b3 -u nacos -w nacos

yml配置

server:
  port: 9005
  servlet:
    context-path: /provider

spring:
  application:
    name: provider-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    alibaba:
      seata:          
        tx-service-group: ${spring.application.name}-group
         
  datasource:
    #type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/seata_storage?userUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root
  
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: provider.domain

业务逻辑代码忽略,提供一个API接口供my-service通过open-feign方式调用即可。

 

使用Seata对数据源进行代理

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.transaction.SpringManagedTransactionFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import com.alibaba.druid.pool.DruidDataSource;

import io.seata.rm.datasource.DataSourceProxy;

/**
 * 使用seata对数据源进行代理
 */
@Configuration
public class DataSourceConfiguration {

	@Bean
	@ConfigurationProperties(prefix = "spring.datasource")
	public DataSource druidDataSource() {
		return new DruidDataSource();
	}
	
	@Bean
	public DataSourceProxy dataSourceProxy(DataSource datasource) {
		return new DataSourceProxy(datasource);
	}
	
	 /**
     * 将原有的DataSource对象替换为DataSourceProxy
     */
    @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();
    }
}

 

步骤二、修改my-service项目

 

yml修改

server:
  port: 9004
  servlet:
    context-path: /my-service

spring:
  application:
    name: my-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    alibaba:
      seata:          
        tx-service-group: my-service-group
         
  datasource:
    #type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/seata_order?userUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root

修改file.conf文件

添加如下内容

store {
  ## store mode: file、db、redis
  mode = "db"
  ## database store property
  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"
    user = "root"
    password = "root"
    minConn = 5
    maxConn = 100
    globalTable = "global_table"
    branchTable = "branch_table"
    lockTable = "lock_table"
    queryLimit = 100
    maxWait = 5000
  }

  }

启动类注解修改

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

使用Seata对数据源进行代理,见创建provider-service项目中的DataSourceConfiguration

 

添加@GlobalTransactional注解

在需要分布式事务的业务方法上添加@GlobalTransaction注解

@GlobalTransactional(name = "txName", rollbackFor = Exception.class)

 

步骤三、创建undo_log表

分别为my-service和provider-service所使用的数据创建undo_log表

README-zh.md文件中已经准备好了

https://github.com/seata/seata/tree/develop/script/client下载mysql.sql

分别在两个数据库下执行mysql.sql即可。

 

操作回滚时,会在log中出现以下日志信息:

 

Seata原理详见这里

具体项目代码见github,相关源码

不当之处,欢迎指出

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值