seata db模式,nacos注册中心,spring boot ,spring cloud ,jdk1.8 完成的配置步骤

1. 环境准备

确保以下环境已经安装并正常运行:

  • JDK 1.8
  • MySQL(或其他支持的数据库)
  • Nacos Server(用于注册中心和配置中心)
  • Seata Server

2. 配置 Seata Server

(1) 下载并解压 Seata

Seata 官方 GitHub 下载最新版本的 Seata,并解压到你的服务器上。

(2) 初始化 Seata 数据库表

在 MySQL 中创建一个数据库(如 seata),并执行 Seata 提供的 SQL 脚本 db_store.sql,初始化以下表:

  • global_table
  • branch_table
  • lock_table

示例脚本路径:seata/conf/db_store.sql

复制代码
CREATE DATABASE seata;

USE seata;

-- global_table
CREATE TABLE IF NOT EXISTS `global_table` (
  `xid` VARCHAR(128) NOT NULL,
  `transaction_id` BIGINT,
  `status` TINYINT NOT NULL,
  `application_id` VARCHAR(32),
  `transaction_service_group` VARCHAR(32),
  `transaction_name` VARCHAR(128),
  `timeout` INT,
  `begin_time` BIGINT,
  `application_data` VARCHAR(2000),
  `gmt_create` DATETIME,
  `gmt_modified` DATETIME,
  PRIMARY KEY (`xid`),
  KEY `idx_gmt_modified_status` (`gmt_modified`, `status`),
  KEY `idx_transaction_id` (`transaction_id`)
);

-- branch_table
CREATE TABLE IF NOT EXISTS `branch_table` (
  `branch_id` BIGINT NOT NULL,
  `xid` VARCHAR(128) NOT NULL,
  `transaction_id` BIGINT,
  `resource_group_id` VARCHAR(32),
  `resource_id` VARCHAR(256),
  `branch_type` VARCHAR(8),
  `status` TINYINT,
  `client_id` VARCHAR(64),
  `application_data` VARCHAR(2000),
  `gmt_create` DATETIME,
  `gmt_modified` DATETIME,
  PRIMARY KEY (`branch_id`),
  KEY `idx_xid` (`xid`)
);

-- lock_table
CREATE TABLE IF NOT EXISTS `lock_table` (
  `row_key` VARCHAR(128) NOT NULL,
  `xid` VARCHAR(96),
  `transaction_id` BIGINT,
  `branch_id` BIGINT NOT NULL,
  `resource_id` VARCHAR(256),
  `table_name` VARCHAR(32),
  `pk` VARCHAR(36),
  `gmt_create` DATETIME,
  `gmt_modified` DATETIME,
  PRIMARY KEY (`row_key`)
);

(3) 修改 registry.conf

编辑 seata/conf/registry.conf 文件,将注册中心和配置中心设置为 Nacos。

复制代码
registry {
  type = "nacos"
  nacos {
    application = "seata-server"
    serverAddr = "127.0.0.1:8848"
    group = "SEATA_GROUP"
    namespace = ""
  }
}

config {
  type = "nacos"
  nacos {
    serverAddr = "127.0.0.1:8848"
    group = "SEATA_GROUP"
    namespace = ""
    dataId = "seataServer.properties"
  }
}

(4) 修改 file.conf

编辑 seata/conf/file.conf 文件,将存储模式设置为 db,并配置数据库连接信息。

复制代码
store {
  mode = "db"
  db {
    datasource = "druid"
    dbType = "mysql"
    driverClassName = "com.mysql.cj.jdbc.Driver"
    url = "jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC"
    user = "root"
    password = "password"
  }
}

(5) 启动 Seata Server

运行以下命令启动 Seata Server:

复制代码
sh seata-server.sh -p 8091 -m db
  • -p:指定 Seata Server 的端口号,默认是 8091。
  • -m:指定存储模式,这里设置为 db

3. 配置微服务

(1) 引入依赖

在每个微服务的 pom.xml 文件中添加 Seata 和 Spring Cloud 相关依赖。

复制代码
<dependencies>
  <!-- Spring Boot Starter -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <!-- Spring Cloud Alibaba Seata Starter -->
  <dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>1.6.0</version> <!-- 请根据实际版本号调整 -->
  </dependency>

  <!-- Spring Cloud Alibaba Nacos Discovery -->
  <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2022.0.0.0</version> <!-- 请根据实际版本号调整 -->
  </dependency>

  <!-- 数据库相关依赖 -->
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
  </dependency>
  <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.0</version> <!-- 请根据实际版本号调整 -->
  </dependency>
</dependencies>

(2) 创建 UNDO_LOG

在每个微服务使用的数据库中,创建 UNDO_LOG 表。这是 AT 模式所需的回滚日志表。

复制代码
CREATE TABLE IF NOT EXISTS `undo_log` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `branch_id` BIGINT(20) NOT NULL,
  `xid` VARCHAR(100) NOT NULL,
  `context` VARCHAR(128) NOT NULL,
  `rollback_info` LONGBLOB NOT NULL,
  `log_status` INT(11) NOT NULL,
  `log_created` DATETIME NOT NULL,
  `log_modified` DATETIME NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

(3) 配置 application.yml

在每个微服务的 application.yml 文件中,配置 Seata、Nacos 和数据库连接信息。

复制代码
spring:
  application:
    name: order-service # 微服务名称
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # Nacos 服务器地址
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/order_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
    username: root
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver

seata:
  enabled: true
  tx-service-group: my_tx_group # 自定义事务组名称
  service:
    vgroup-mapping:
      my_tx_group: default # 映射到 Seata Server 的事务组
    grouplist:
      default: 127.0.0.1:8091 # Seata Server 地址
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
  data-source-proxy-mode: AT # 数据源代理模式,支持 AT、XA,默认为 AT

(4) 数据源代理

为了让 Seata 拦截业务 SQL 并生成回滚日志,需要对数据源进行代理。Spring Boot 项目中可以通过 @EnableAutoDataSourceProxy 注解自动完成代理。

主类示例:

复制代码
@SpringBootApplication
@EnableAutoDataSourceProxy
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

(5) 开启全局事务

在需要使用分布式事务的方法上,添加 @GlobalTransactional 注解。

复制代码
@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private InventoryService inventoryService;

    @GlobalTransactional
    public void createOrder(Order order) {
        // 创建订单
        orderMapper.insert(order);

        // 扣减库存
        inventoryService.reduceStock(order.getProductId(), order.getCount());
    }
}

4. 测试与验证

  1. 启动 Nacos Server。
  2. 启动 Seata Server。
  3. 启动所有微服务。
  4. 测试一个包含多个微服务调用的分布式事务场景,确保事务能够正确提交或回滚。

总结

通过以上步骤,你可以成功地在 Spring Boot、Spring Cloud 和 Nacos 环境下集成 Seata 的 DB 模式,实现分布式事务管理。关键点包括:

  • 配置 Seata Server 并初始化事务日志表。
  • 在微服务中引入 Seata 依赖,创建 UNDO_LOG 表。
  • 使用 application.yml 配置 Seata、Nacos 和数据库连接信息。
  • 使用 @GlobalTransactional 注解开启全局事务。

这样可以确保你的微服务架构具备强大的分布式事务管理能力,同时保持代码的简洁性和可维护性。


几种模式的对比以及运用

1. AT 模式 vs TCC 模式

特性 AT 模式 TCC 模式
数据源代理 需要数据源代理(@EnableAutoDataSourceProxy 不需要数据源代理
回滚机制 自动通过 UNDO_LOG 表生成回滚日志 手动实现 TryConfirmCancel 方法
适用场景 适用于大多数 CRUD 场景 适用于复杂业务场景,要求更高的灵活性
配置复杂度 简单,仅需创建 UNDO_LOG 复杂,需手动编写补偿逻辑

2. 使用 TCC 模式的配置与代码调整

(1) 修改 data-source-proxy-mode

application.yml 中,将数据源代理模式设置为 none,因为 TCC 模式不需要数据源代理。

复制代码
seata:
  data-source-proxy-mode: none # TCC 模式不使用数据源代理

(2) 编写 TCC 接口

TCC 模式要求开发者手动实现三个阶段的方法:TryConfirmCancel

示例:

复制代码
@LocalTCC
public interface AccountService {

    /**
     * Try 阶段:预留资源
     */
    @TwoPhaseBusinessAction(name = "accountTccAction", commitMethod = "confirm", rollbackMethod = "cancel")
    boolean tryFreeze(@BusinessActionContextParameter(paramName = "userId") String userId,
                      @BusinessActionContextParameter(paramName = "amount") BigDecimal amount);

    /**
     * Confirm 阶段:确认操作
     */
    boolean confirm(BusinessActionContext context);

    /**
     * Cancel 阶段:取消操作
     */
    boolean cancel(BusinessActionContext context);
}

(3) 实现 TCC 方法

实现上述接口中的三个方法。

示例:

复制代码
@Service
public class AccountServiceImpl implements AccountService {

    @Override
    public boolean tryFreeze(String userId, BigDecimal amount) {
        // 尝试冻结用户的资金
        System.out.println("Try to freeze account: " + userId + ", amount: " + amount);
        return true; // 返回是否成功
    }

    @Override
    public boolean confirm(BusinessActionContext context) {
        // 确认扣款
        String userId = (String) context.getActionContext("userId");
        BigDecimal amount = (BigDecimal) context.getActionContext("amount");
        System.out.println("Confirm account: " + userId + ", amount: " + amount);
        return true;
    }

    @Override
    public boolean cancel(BusinessActionContext context) {
        // 取消冻结
        String userId = (String) context.getActionContext("userId");
        BigDecimal amount = (BigDecimal) context.getActionContext("amount");
        System.out.println("Cancel account: " + userId + ", amount: " + amount);
        return true;
    }
}

(4) 开启全局事务

在调用 TCC 方法时,仍然需要使用 @GlobalTransactional 注解开启全局事务。

示例:

复制代码
@Service
public class OrderService {

    @Autowired
    private AccountService accountService;

    @GlobalTransactional
    public void createOrder(Order order) {
        // 调用 TCC 方法
        boolean result = accountService.tryFreeze(order.getUserId(), order.getAmount());
        if (!result) {
            throw new RuntimeException("Failed to freeze account");
        }
        // 其他业务逻辑
    }
}

3. 使用 SAGA 模式的配置与代码调整

SAGA 模式是一种基于状态机的分布式事务管理方式,适用于长事务场景。

(1) 配置 Saga 模式

application.yml 中,无需特别指定模式,因为 Saga 模式是通过状态机 DSL 文件定义的。

(2) 创建状态机 DSL 文件

Saga 模式需要一个状态机描述文件(JSON 格式),定义事务的各个阶段和补偿逻辑。

示例:

复制代码
{
  "name": "orderSaga",
  "version": "1.0.0",
  "startState": "createOrder",
  "states": {
    "createOrder": {
      "type": "ServiceTask",
      "serviceMethod": "orderService.createOrder",
      "compensateState": "cancelOrder"
    },
    "cancelOrder": {
      "type": "Compensation",
      "serviceMethod": "orderService.cancelOrder"
    }
  }
}

(3) 引入 Saga Starter

在微服务中引入 Saga Starter 依赖。

复制代码
<dependency>
  <groupId>io.seata</groupId>
  <artifactId>seata-saga-starter</artifactId>
  <version>1.6.0</version>
</dependency>

(4) 启动 Saga 状态机

通过 Saga 状态机启动事务。

复制代码
@Autowired
private StateMachineEngine stateMachineEngine;

public void startSaga() {
    Map<String, Object> params = new HashMap<>();
    params.put("userId", "123");
    params.put("amount", 100);
    stateMachineEngine.start("orderSaga", null, params);
}

4. 使用 XA 模式的配置与代码调整

XA 模式直接依赖数据库的 XA 协议实现分布式事务。

(1) 修改 data-source-proxy-mode

application.yml 中,将数据源代理模式设置为 XA

复制代码
seata:
  data-source-proxy-mode: XA

(2) 数据库支持

确保你的数据库支持 XA 协议(如 MySQL、Oracle 等)。

(3) 开启全局事务

与其他模式相同,仍然需要使用 @GlobalTransactional 注解。

复制代码
@Service
public class OrderService {

    @GlobalTransactional
    public void createOrder(Order order) {
        // 业务逻辑
    }
}

5. 总结

  • AT 模式:简单易用,适合大多数 CRUD 场景,自动管理回滚日志。
  • TCC 模式:灵活但复杂,需要手动实现补偿逻辑,适合复杂业务场景。
  • SAGA 模式:基于状态机,适合长事务场景。
  • XA 模式:依赖数据库的 XA 协议,性能较低,适合对一致性要求极高的场景。

根据你的业务需求选择合适的模式,并按照上述步骤进行配置和代码调整。

相关推荐
qq_334466861 分钟前
U9补丁同步的时候报错
数据库
蛐蛐蜉蝣耶2 分钟前
Spring Boot实现DynamicMethodMatcherPointcut示例
java·spring boot·后端
施嘉伟4 分钟前
KSQL Developer 测试记录
数据库·kingbase
谱度众合9 分钟前
【蛋白互作研究】邻近标记PL-MS实验指南:如何精准获取目标蛋白的基因序列?
数据库·科技·蛋白质组学·药物靶点·生物科研
码农小卡拉10 分钟前
Springboot “钩子”:@PostConstruct注解
java·spring boot·后端·spring·spring cloud
奔波霸的伶俐虫18 分钟前
spring boot集成kafka学习
spring boot·学习·kafka
麦聪聊数据18 分钟前
生成测试数据(三):从建表到 CRUD 的冷启动
数据库·sql
内存不泄露20 分钟前
基于Spring Boot和Vue的在线考试系统设计与实现
vue.js·spring boot·后端
Awkwardx21 分钟前
MySQL数据库—MySQL复合查询
数据库·mysql
2301_8002561122 分钟前
R-Tree创建与遍历,R-Tree在4类空间查询中的应用,实现4类空间查询的各类算法[第8章]
数据库·算法·机器学习·postgresql·r-tree