微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SpringCloud Seata 1.0

Seata 为什么出现

分布式事务的解决方案,来保证其发生异常时,该业务调用的全部服务关于数据修改,新增的操作,要么都成功,要么都失败。保证数据的正确性。

Seata 的基本概念

  1. Transaction ID:全局事务ID
  2. TC:总控制器,统一管理各个服务的事务提交和回滚。
  3. TM:分布式事务的发动者。控制其范围,确认有哪些服务的事务要管理。
  4. RM:各个服务的事务执行情况,将提交,还是回滚的执行情况反馈给TC,让TC来决定整体事务是提交还是回滚操作。

Seata 安装使用

  1. 从官网 http://seata.io/zh-cn/ 下载对应版本zip包 解压到本地后修改config目录下的file.conf配置文件,设置自定义事务组名称数据库地址

    在这里插入图片描述


    file.conf文件中的service模块的vgroup_mapping.my_test_tx_group 设置自定义事务组名称
service {
 # 修改事务组的名称为 fsp_tx_group 随便定义
  vgroup_mapping.my_test_tx_group = "fsp_tx_group"
 
  default.grouplist = "127.0.0.1:8091"
  enableDegrade = false
  disable = false
  max.commit.retry.timeout = "-1"
  max.rollback.retry.timeout = "-1"
}

修改file.conf文件中的store 模块,将模式从file变成db,对应的db数据库配置相应的信息

## transaction log store
store {
  ## store mode: file、db
  mode = "db"
 
  ## file store
  file {
    dir = "sessionStore"
 
    # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
    max-branch-session-size = 16384
    # globe session size , if exceeded throws exceptions
    max-global-session-size = 512
    # file buffer size , if exceeded allocate new buffer
    file-write-buffer-cache-size = 16384
    # when recover batch read size
    session.reload.read_size = 100
    # async, sync
    flush-disk-mode = async
  }
 
  ## database store
  db {
    ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc.
    datasource = "dbcp"
    ## MysqL/oracle/h2/oceanbase etc. MysqL 数据库连接信息
    db-type = "MysqL"
    driver-class-name = "com.MysqL.jdbc.Driver"
    # 对应的数据库
    url = "jdbc:MysqL://127.0.0.1:3306/seata"
    user = "root"
    password = "1234qwer"
    min-conn = 1
    max-conn = 3
    # 下面为对应的服务事务存在快照信息的表名  全局,分支,行锁
    global.table = "global_table"
    branch.table = "branch_table"
    lock-table = "lock_table"
    query-limit = 100
  }
}
  1. 执行conf目录的db_store.sql的语句创建上面配置的全局,分支,行锁表

    在这里插入图片描述

  2. 配置conf目录的registry.conf文件设置注册中心类型和地址
registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  # 类型设置为nacos
  type = "nacos"
 
  nacos {
  	# 地址设置本地 8848端口
    serverAddr = "localhost:8848"
    namespace = ""
    cluster = "default"
  }
  ......

就可以先启动nacos再到seata的bin目录下启动seata 查看是否成功

在这里插入图片描述

Seata 分布式事务发起端搭建

  1. 添加依赖
        <!--nacos-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--seata-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            <!-- 如果seata的版本和使用的版本不一致 要先删掉再添加上对应版本的seata-->
            <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>
        <!--feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--web-actuator-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
  1. 配置yml文件
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:
    driver-class-name: com.MysqL.jdbc.Driver
    url: jdbc:MysqL://localhost:3306/seata_order
    username: root
    password: 123456

feign:
  hystrix:
    enabled: false

logging:
  level:
    io:
      seata: info

mybatis:
  mapperLocations: classpath:mapper/*.xml
  1. 拷贝seata的file.conf和registry.conf文件到application.yml同级目录。文件修改内容和上面介绍的一样。

    在这里插入图片描述


    在这里插入图片描述


    在这里插入图片描述

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

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

  1. 编写测试业务方法 使用@GlobalTransactional注解实现分布式事务。
   /**
     * 创建订单->调用库存服务扣减库存->调用账户服务扣减账户余额->修改订单状态
     * 简单说:下订单->扣库存->减余额->改状态  可以实现当某个微服务失败时,其他成功的微服务数据会回滚数据。
     */
    @Override
    // 设置全局事务名称 
    @GlobalTransactional(name = "fsp-create-order",rollbackFor = Exception.class)
    public void create(Order order)
    {
        log.info("----->开始新建订单");
        //1 新建订单
        orderDao.create(order);

        //2 扣减库存
        log.info("----->订单微服务开始调用库存,做扣减Count");
    storageService.decrease(order.getProductId(),order.getCount());
        log.info("----->订单微服务开始调用库存,做扣减end");

        //3 扣减账户
        log.info("----->订单微服务开始调用账户,做扣减Money");
       accountService.decrease(order.getUserId(),order.getMoney());
        log.info("----->订单微服务开始调用账户,做扣减end");

        //4 修改订单状态,从零到1,1代表已经完成
        log.info("----->修改订单状态开始");
        orderDao.update(order.getUserId(),0);
        log.info("----->修改订单状态结束");

        log.info("----->下订单结束了,O(∩_∩)O哈哈~");

    }

其他的服务和该发起端服务配置上没有区别,就是@GlobalTransactional注解在对应的业务实现上不必写。

Seata 原理简介

在一阶段,Seata 会拦截“业务 sql”,
1 解析 sql 语义,找到“业务 sql”要更新的业务数据,在业务数据被更新前,将其保存成“before image”,
2 执行“业务 sql”更新业务数据,在业务数据更新之后,
3 其保存成“after image”,最后生成行锁。
以上操作全部在一个数据库事务内完成,这样保证了一阶段操作的原子性。

在这里插入图片描述


如果都正常,则将before image和after image 和行锁生成的表数据删掉,正常的修改对应业务表数据
如果其中一个失败了,就要通过对应的before image来还原数据,而还原数据前要通过after image 和现在数据库对应数据比较是否一致,是否发生脏写,脏写要自行处理。没有脏写,才可以将数据还原。

原文地址:https://www.jb51.cc/wenti/3287615.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐