分布式事务seata

一、什么是事务

事务是逻辑上的一组执行单元,要么都执行,要么都不执行.

比如: 张三给李四转1000元钱, 涉及到二个操作 张三的账户-1000 李四的账户+1000 上诉二个步骤要么一起成功,要么一起失败. 不存在张三的钱扣了,李四 没收到转账。

1.1 事物的特性(ACID)

在这里插入图片描述

ACID是指数据库管理系统DBMS中事物所具有四个特性

①:atomicity【原子性】 原子性表现为操作不能被分割,那么这二个操作 要么同时完成,要 么就全部不完成,若事务出错了,那么事务就会回滚, 好像什么都没有发生过

②:Consistency【一致性】 一致性也比较容易理解,也就是说数据库要一直处于一致的状态, 事务开始前是一个一致状态,事务结束后是另一个一致状态, 事务将数据库从一个一致状态转移到另一个一致状态

③:Isolation【隔离性】所谓的独立性就是指并发的事务之间不会互相影响,如果一个事务 要访问的数据正在被另外一个事务修改,只要另外一个事务还未提交,它 所访问的数据就不受未提交事务的影响。换句话说,一个事务的影响在该 事务提交前对其它事务是不可见的

④:Durability【持久性】 若事务已经提交了,那么就回在数据库中永久的保存下来

1.2 什么是分布式事务?

分布式事务:就是把各个节点上的微服务的本地事务结合起来,看成一个整体的事务。
在这里插入图片描述
分布式事务组成部分:

①:事务参与者(就是我们的一个一个的微服务,比如订单服务,库存服务)

②:资源服务器(说白了就是我们的对应微服务连接的数据库 比如订单库,库存库)

③:事务管理器 (用于决策各个事务参数者的提交和回滚)

二、什么是Seata

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用 的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事 务模式,为用户打造一站式的分布式解决方案(AT模式是阿里首推的模式, 阿里云上有商用版本的GTS[Global Transaction service 全局事务服 务] ) 。

Seata中有个角色 : RM和TM

RM:资源管理者,可以理解为我们的一个一个的微服务 也叫做事务的参与者.

TM: 事务管理者也是我们的一个微服务,但是该微服务是 一个带头大哥,充当全局事务的发起者(决定了全局事务的开启,回滚,提交等) ***凡是我们的微服务中标注了@GlobalTransactional ,那么该微服务就会被看出 一个TM。我们业务场景中订单微服务就是一个事务发起者,同时也是一个RM TC(全局事务的协调者):这里就是我们的Seata-server,用来保存全局事务,分支 事务,全局锁等记录,然后会通知各个RM进行回滚或者提交.

二:整体机制(两阶段提交协议的演变)

在这里插入图片描述

三、快速开始搭建seata-server环境
3.1 seata-server的下载和解压

https://github.com/seata/seata/releases 下载seata-server包(本文下载的是0.9.0)
在这里插入图片描述
解压我们的下载包seata-server包,解压的路径结构
在这里插入图片描述

3.2 执行db_store.sql

第三步: 进入conf目录下 拿到db_store.sql脚本 ,然后再本地数据库创建一个seata的数据库,执行脚本db_store.sql。
在这里插入图片描述

3.3 修改conf目录下的file.conf文件

1、修改的节点: service节点

service {
  #vgroup->rgroup
  //修改全局事务分组
  vgroup_mapping.store_tx_group = "default"
  //#seata‐server的连接地址
  default.grouplist = "127.0.0.1:8091"
  //忽略....
}

2、修改store节点:

## transaction log store
store {
  ## store mode: file、db
  //存储模式 使用db
  mode = "db"
 //忽略....
  db {
    ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc.
    //数据源的类型
    datasource = "dbcp"
    ## mysql/oracle/h2/oceanbase etc.
    db-type = "mysql"
    driver-class-name = "com.mysql.jdbc.Driver"
    //你seata库的地址
    url = "jdbc:mysql://127.0.0.1:3306/seata"
    user = "root"
    password = "YCLh2o2@"
    min-conn = 1
    max-conn = 3
    global.table = "global_table"
    branch.table = "branch_table"
    lock-table = "lock_table"
    query-limit = 100
  }
}
3.4 修改conf目录下的register.conf文件

1、修改registry节点的type类型为nacos

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

  nacos {
    //nacos地址
    serverAddr = "192.168.93.224:8848"
    namespace = ""
    cluster = "default"
  }
 //忽略...
}

2、修改config节点的type改为nacos

config {
  # file、nacos 、apollo、zk、consul、etcd3
  type = "nacos"

  nacos {
    //nacos地址
    serverAddr = "192.168.93.224:8848"
    namespace = ""
  }
  //忽略...
}
3.5 修改conf文件下的nacos-config.txt文件
//忽略。。。。
service.vgroup_mapping.store_tx_group=default
//忽略。。。。
store.mode=db  //修改存储模式是db
//忽略。。。。
store.db.datasource=druid //数据源
store.db.db-type=mysql
store.db.driver-class-name=com.mysql.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata
store.db.user=root
store.db.password=YCLh2o2@
//忽略。。。。
3.6 执行nacos-config.sh

在/seata/conf目录执行下面的命令,把seata的配置导入到nacos的配置中心上去

#192.168.93.224是nacos服务器的ip
sh nacos-config.sh 192.168.93.224

在这里插入图片描述

3.7 启动 seata-server服务

进入seata的bin目录点击执行seata-server.sh脚步

sh seata-server.sh

在这里插入图片描述
出现这个就表示seata-server环境搭建成功了,下面开始在项目中使用seata

四、微服务使用seata
4.1 添加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-all</artifactId>
    <version>0.9.0</version>
</dependency>
4.2 写配置添加代理数据源配置
@Configuration
@MapperScan(basePackages = {"com.clyu.shop.store.mapper"})
public class MyBatisConfig {


    /**
     * 从配置文件获取属性构造datasource,注意前缀,这里用的是druid,根据自己情况配置,
     * 原生datasource前缀取"spring.datasource"
     *
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.hikari")
    public DataSource hikariDataSource() {
        return new HikariDataSource();
    }

    /**
     * 构造datasource代理对象,替换原来的datasource
     *
     * @param hikariDataSource
     * @return
     */
    @Primary
    @Bean("dataSource")
    public DataSourceProxy dataSourceProxy(DataSource hikariDataSource) {
        return new DataSourceProxy(hikariDataSource);
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DataSourceProxy dataSourceProxy) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:/mybatis/mapper/**/*.xml"));
        sqlSessionFactoryBean.setConfigLocation(new PathMatchingResourcePatternResolver().getResource("classpath:/mybatis/mybatis-config.xml"));
        sqlSessionFactoryBean.setTypeAliasesPackage("com.clyu.shop.entity");
        sqlSessionFactoryBean.setDataSource(dataSourceProxy);
        return sqlSessionFactoryBean;
    }
}

然后启动类上利用@SpringBootApplication注解排除原数据源DataSourceAutoConfiguration

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableDiscoveryClient
@EnableFeignClients(basePackages="com.clyu.shop.feign.*")
@ComponentScans({
        @ComponentScan("com.clyu.shop.feign.handler")
})
public class StoreApplication {

    public static void main( String[] args )
    {
        SpringApplication.run(StoreApplication.class, args);
    }
}
4.3 修改配置文件 yml中添加配置文件
spring:
  cloud:
    alibaba:
      seata:
        tx‐service‐group : store_tx_group
        ##seata配置(配置事务组 需要和seata‐server的配置一样)

修改file.conf 和register.conf文件(跟seata-server的改动一样)
在这里插入图片描述

4.4 在当前微服务的数据库中执行db_undo_log.sql

在这里插入图片描述

4.5 微服务发起者需要写全局事务注解

这里是store服务为发起者

@Service
public class StoreServiceImpl implements StoreService {

    @Resource
    private StoreMapper storeMapper;

    @Resource
    private OrderFeignApi orderFeignApi;

    @GlobalTransactional(name = "store_tx_group",rollbackFor = Exception.class)
    @Override
    public void insert(Store store) {
        Order order = new Order();
        order.setOrderNo("1");
        order.setProductName("iphone11");
        order.setProductNumber(1);
        order.setUserName("俞朝磊");
        orderFeignApi.insertOrder(order);

        store.setId(UUIDUtils.getUUID());
        storeMapper.insert(store);
        int i = 1/0;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值