Seata服务搭建&配置&使用

是什么

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

image-20230306140310664

Seata 组成

全局事务ID XID

TC (Transaction Coordinator) - 事务协调者
维护全局和分支事务的状态,驱动全局事务提交或回滚。

TM (Transaction Manager) - 事务管理器
定义全局事务的范围:开始全局事务、提交或回滚全局事务。

RM (Resource Manager) - 资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

工作流程

见官网

简单的说就是:
a.申请全局事务ID
b.进行本地事务操作
c.提交或回滚后释放全局事务

Seata服务部署(MySql+Nacos)

下载

23/03/06最新稳定版1.6.1

Releases · seata/seata (github.com)

创建Seata数据库

进入下载后解压目录,有sql

seata\script\server\db

修改配置

找到解压后目录seata\conf,修改application.yml

分别修改seata:config、registry、store

#  Copyright 1999-2019 Seata.io Group.
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#  http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

server:
  port: 7091

spring:
  application:
    name: seata-server

# 日志相关配置
logging:
  config: classpath:logback-spring.xml
  file:
    path: ${user.home}/logs/seata
  extend:
    logstash-appender:
      destination: 127.0.0.1:4560
    kafka-appender:
      bootstrap-servers: 127.0.0.1:9092
      topic: logback_to_logstash

console:
  user:
    username: seata
    password: seata

seata:
	# 配置可从nacos读取,nacos使用见 https://www.cnblogs.com/rb2010/p/17145183.html
	# config下配置内容见 解压目录seata\conf\application.example.yml
  config:
    # support: nacos, consul, apollo, zk, etcd3
    type: nacos
    nacos:
      server-addr: 10.20.30.227:9999 #nacos地址
      namespace:
      group: SEATA_GROUP
      username:
      password:
      context-path:
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key:
      #secret-key:
      data-id: seataServer.properties #nacos配置的data-id
     # 将seata注册进nacos
  registry:
    # support: nacos, eureka, redis, zk, consul, etcd3, sofa
    type: nacos
    nacos:
      application: seata-server
      server-addr: 10.20.30.227:9999
      group: SEATA_GROUP
      namespace:
      cluster: default
      username:
      password:
      context-path:
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key:
      #secret-key:
     #修改事务信息存储到MySql
  store:
    # support: file 、 db 、 redis
    mode: db
    db:
      datasource: druid
      db-type: mysql
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://10.20.30.13:3306/seata?rewriteBatchedStatements=true
      user: root
      password: root
      min-conn: 10
      max-conn: 100
      global-table: global_table
      branch-table: branch_table
      lock-table: lock_table
      distributed-lock-table: distributed_lock
      query-limit: 1000
      max-wait: 5000
#  server:
#    service-port: 8091 #If not configured, the default is '${server.port} + 1000'
  security:
    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
    tokenValidityInMilliseconds: 1800000
    ignore:
      urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login

启动&验证

注: 堆内存建议分配2G,堆外内存1G

执行seata\bin下seata-server.bat或seata-server.sh

访问http://10.20.30.94:7091/

SeataDocker\K8S\高可用部署

见官网

项目搭建

本次测试准备使用三个项目,订单、库存、积分,流程为下单后减库存加积分

数据库

a.积分库

CREATE DATABASE /*!32312 IF NOT EXISTS*/`integral` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `integral`;
/*Table structure for table `integral` */
DROP TABLE IF EXISTS `integral`;

CREATE TABLE `integral` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `count` int(11) DEFAULT NULL COMMENT '积分',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

b.订单库

CREATE DATABASE /*!32312 IF NOT EXISTS*/`order` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `order`;

/*Table structure for table `order` */

DROP TABLE IF EXISTS `order`;

CREATE TABLE `order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_no` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

c.库存库

CREATE DATABASE /*!32312 IF NOT EXISTS*/`stock` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `stock`;

/*Table structure for table `stock` */

DROP TABLE IF EXISTS `stock`;

CREATE TABLE `stock` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `stock` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

业务代码

订单服务

pom

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>4.1.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.6</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.seata/seata-spring-boot-starter -->
        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
            <version>1.6.1</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            <version>2021.1</version>
            <exclusions>
                <exclusion>
                    <groupId>io.seata</groupId>
                    <artifactId>seata-spring-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
 </dependencies>

application.yml

todo default_tx_group

server:
  port: 8081
spring:
  application:
    name: order-project
  cloud:
    nacos:
      discovery:
        server-addr: 10.20.30.227:9999
    alibaba:
      seata:
        default_tx_group: my_tx #nacos配置,具体见下图
  #shardingsphere相关配置
  shardingsphere:
    datasource:
      names: masterdb,slavedb1   #库名,只是名字
      masterdb: #主库
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/order?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
        username: root
        password: 123
      slavedb1: #从库1
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/order?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
        username: root
        password: 123

    masterslave:
      name: dbs
      master-data-source-name: masterdb #主库
      slave-data-source-names: slavedb1 #多个从库
      load-balance-algorithm-type: ROUND_ROBIN #RANDOM随机  ROUND_ROBIN 轮训
    props:
      sql:
        show: true #输出日志

启动类

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class);
    }
}

service

IntegralService.java

@Service
@FeignClient(value = "integral-project") //后面积分服务的服务名称
public interface IntegralService  {
    @GetMapping(value = "/saveIntegral") //后面积分服务的接口地址
    void saveIntegral(@RequestParam("integralId") Integer integralId );
}

StockService.java

@Service
@FeignClient(value = "stock-project") //后面库存服务的服务名称
public interface StockService  {
    @GetMapping("/stock") //后面库存服务的接口地址
    void stock(@RequestParam(value = "stockId") Integer stockId);
}

controller

@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    private OrderService orderService;
    @Autowired
    private IntegralService integralService;
    @Autowired
    private StockService stockService;

    @GetMapping("saveOrder")
    @GlobalTransactional //开启分布式事务
    public void saveOrder(){
        Order order=new Order();
        order.setOrderNo(LocalDateTime.now().toString());
        orderService.save(order);
        stockService.stock(1);
        integralService.saveIntegral(1);
    }

}

库存服务

pom

同订单服务

yml

server:
  port: 8082
spring:
  application:
    name: stock-project
  cloud:
    alibaba:
      seata:
        default_tx_group: my_tx #nacos配置
    nacos:
      discovery:
        server-addr: 10.20.30.227:9999
  #shardingsphere相关配置
  shardingsphere:
    datasource:
      names: masterdb,slavedb1   #库名,只是名字
      masterdb: #主库
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/stock?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
        username: root
        password: 123
      slavedb1: #从库1
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/stock?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
        username: root
        password: 123

    masterslave:
      name: dbs
      master-data-source-name: masterdb #主库
      slave-data-source-names: slavedb1 #多个从库
      load-balance-algorithm-type: ROUND_ROBIN #RANDOM随机  ROUND_ROBIN 轮训
    props:
      sql:
        show: true #输出日志

controller

@RestController
public class StockController {
    @Autowired
    private StockService stockService;

    @GetMapping("stock")
    public void stock(Integer stockId){
        Stock stock = stockService.getById(stockId);
        stock.setStock(stock.getStock()-1);
        stockService.updateById(stock);
    }

}

启动类

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class StockApplication {
    public static void main(String[] args) {
        SpringApplication.run(StockApplication.class,args);
    }
}

积分服务

pom

同订单服务

yml

server:
  port: 8083
spring:
  application:
    name: integral-project
  cloud:
    alibaba:
      seata:
        default_tx_group: my_tx #nacos配置
    nacos:
      discovery:
        server-addr: 10.20.30.227:9999
  #shardingsphere相关配置
  shardingsphere:
    datasource:
      names: masterdb,slavedb1   #库名,只是名字
      masterdb: #主库
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/integral?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
        username: root
        password: 123
      slavedb1: #从库1
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/integral?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
        username: root
        password: 123

    masterslave:
      name: dbs
      master-data-source-name: masterdb #主库
      slave-data-source-names: slavedb1 #多个从库
      load-balance-algorithm-type: ROUND_ROBIN #RANDOM随机  ROUND_ROBIN 轮训
    props:
      sql:
        show: true #输出日志

controller

@RestController
public class IntegralController {
    @Autowired
    private IntegralService integralService;
    @GetMapping("saveIntegral")
    public void saveIntegral(Integer integralId){
        Integral integral = integralService.getById(integralId);
        integral.setCount(integral.getCount()+1);
        integralService.updateById(integral);
    }
}

启动类

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class IntegralApplication {
    public static void main(String[] args) {
        SpringApplication.run(IntegralApplication.class,args);
    }
}

nacos配置

image-20230308172104963

测试

当调用订单服务order/saveOrder时,如果库存服务或者积分服务出异常了,那么三个库都会回滚

本Demo代码

下载

posted @ 2023-03-08 17:28  RollBack2010  阅读(508)  评论(0编辑  收藏  举报