Seata如何搭建与分布式事务入门

发布时间:2021-07-06 18:14:11 作者:chen
来源:亿速云 阅读:260
# Seata如何搭建与分布式事务入门

## 目录
1. [分布式事务基础概念](#一分布式事务基础概念)
   - 1.1 [什么是分布式事务](#11-什么是分布式事务)
   - 1.2 [CAP理论与BASE理论](#12-cap理论与base理论)
   - 1.3 [常见解决方案对比](#13-常见解决方案对比)
2. [Seata核心架构解析](#二seata核心架构解析)
   - 2.1 [TC/TA/RM角色划分](#21-tctarm角色划分)
   - 2.2 [AT模式原理详解](#22-at模式原理详解)
   - 2.3 [TCC/SAGA模式对比](#23-tccsaga模式对比)
3. [Seata Server部署实战](#三seata-server部署实战)
   - 3.1 [单机版部署指南](#31-单机版部署指南)
   - 3.2 [高可用集群配置](#32-高可用集群配置)
   - 3.3 [注册中心与配置中心](#33-注册中心与配置中心)
4. [Spring Cloud集成实践](#四spring-cloud集成实践)
   - 4.1 [Spring Boot Starter配置](#41-spring-boot-starter配置)
   - 4.2 [数据源代理配置](#42-数据源代理配置)
   - 4.3 [全局事务注解使用](#43-全局事务注解使用)
5. [生产环境优化建议](#五生产环境优化建议)
   - 5.1 [参数调优指南](#51-参数调优指南)
   - 5.2 [常见问题排查](#52-常见问题排查)
   - 5.3 [监控与告警配置](#53-监控与告警配置)
6. [实战案例演示](#六实战案例演示)
   - 6.1 [电商下单场景](#61-电商下单场景)
   - 6.2 [跨行转账场景](#62-跨行转账场景)

## 一、分布式事务基础概念

### 1.1 什么是分布式事务

在单体应用架构中,我们通常使用本地事务(如MySQL的InnoDB引擎事务)来保证数据一致性。但当系统演进为微服务架构时,一个业务操作往往需要跨多个服务、多个数据库,这就产生了分布式事务需求。

**典型场景示例**:
```java
// 伪代码展示分布式事务场景
@DistributedTransactional
public void createOrder(OrderDTO order) {
    // 操作1:库存服务扣减库存
    inventoryService.reduceStock(order.getItems());
    
    // 操作2:订单服务创建订单
    orderService.create(order);
    
    // 操作3:账户服务扣减余额
    accountService.debit(order.getUserId(), order.getAmount());
}

1.2 CAP理论与BASE理论

CAP定理(布鲁尔定理)

分布式系统必须满足P,因此在C和A之间需要权衡。Seata采用的AT模式优先保证AP,最终达到C。

BASE理论

1.3 常见解决方案对比

方案 原理 优点 缺点
2PC 两阶段提交 强一致性 同步阻塞、单点问题
TCC Try-Confirm-Cancel 高灵活性 开发复杂度高
SAGA 长事务拆分 适合长流程 无隔离性
本地消息表 异步确保型 简单可靠 时效性差
Seata AT 反向SQL补偿 零侵入、高性能 全局锁竞争

二、Seata核心架构解析

2.1 TC/TA/RM角色划分

Seata如何搭建与分布式事务入门

2.2 AT模式原理详解

阶段一:业务数据+回滚日志入库

-- 原始SQL
UPDATE product SET stock = stock - 1 WHERE id = 1001;

-- Seata代理后实际执行
-- 1. 查询前镜像
SELECT stock FROM product WHERE id = 1001;
-- 2. 执行业务SQL
UPDATE product SET stock = stock - 1 WHERE id = 1001;
-- 3. 查询后镜像
SELECT stock FROM product WHERE id = 1001;
-- 4. 插入undo_log
INSERT INTO undo_log VALUES(...);

阶段二提交流程: 1. TM向TC发起全局提交 2. TC异步删除各分支undo_log

阶段二回滚流程: 1. TM向TC发起全局回滚 2. TC查询undo_log构造补偿SQL

UPDATE product SET stock = stock + 1 WHERE id = 1001;

2.3 TCC/SAGA模式对比

TCC模式开发示例

public interface AccountService {
    @TwoPhaseBusinessAction(name = "debit", commitMethod = "confirm", rollbackMethod = "cancel")
    boolean tryDebit(@BusinessActionContextParameter(paramName = "userId") String userId,
                    @BusinessActionContextParameter(paramName = "money") BigDecimal money);
    
    boolean confirm(BusinessActionContext context);
    boolean cancel(BusinessActionContext context);
}

模式选择建议

三、Seata Server部署实战

3.1 单机版部署指南

步骤1:下载安装包

wget https://github.com/seata/seata/releases/download/v1.5.2/seata-server-1.5.2.tar.gz
tar -zxvf seata-server-1.5.2.tar.gz

步骤2:修改conf/registry.conf

registry {
  type = "nacos"
  nacos {
    serverAddr = "127.0.0.1:8848"
    namespace = ""
    cluster = "default"
  }
}

步骤3:启动服务

sh bin/seata-server.sh -p 8091 -h 127.0.0.1

3.2 高可用集群配置

数据库存储模式配置(conf/file.conf)

store {
  mode = "db"
  db {
    datasource = "druid"
    dbType = "mysql"
    url = "jdbc:mysql://127.0.0.1:3306/seata"
    user = "root"
    password = "123456"
    minConn = 5
    maxConn = 30
  }
}

需要初始化的数据库表

-- 全局事务表
CREATE TABLE IF NOT EXISTS global_table (
  xid VARCHAR(128) NOT NULL PRIMARY KEY,
  ...
);
-- 分支事务表
CREATE TABLE IF NOT EXISTS branch_table (
  branch_id BIGINT NOT NULL PRIMARY KEY,
  xid VARCHAR(128) NOT NULL,
  ...
);

3.3 注册中心与配置中心

Nacos配置中心同步: 1. 将config.txt上传到Nacos

python3 nacos-config.py -h 127.0.0.1 -p 8848 -g SEATA_GROUP -t 5a3c7d6c-f497-4d68-a71a-2e5e1230

四、Spring Cloud集成实践

4.1 Spring Boot Starter配置

pom.xml依赖

<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>1.5.2</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

application.yml配置

seata:
  application-id: order-service
  tx-service-group: my_tx_group
  service:
    vgroup-mapping:
      my_tx_group: default
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848

4.2 数据源代理配置

必须配置项

@Configuration
public class DataSourceConfig {
    
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidDataSource druidDataSource() {
        return new DruidDataSource();
    }

    @Primary
    @Bean("dataSource")
    public DataSource dataSource(DruidDataSource druidDataSource) {
        return new DataSourceProxy(druidDataSource);
    }
}

4.3 全局事务注解使用

基础用法

@GlobalTransactional(timeoutMills = 60000, name = "createOrder")
public void createOrder(Order order) {
    // 1. 扣减库存
    storageFeignService.deduct(order.getCommodityCode(), order.getCount());
    
    // 2. 创建订单
    orderMapper.insert(order);
    
    // 3. 扣减余额
    accountFeignService.debit(order.getUserId(), order.getMoney());
}

注意事项: 1. 避免在事务方法内处理HTTP请求 2. 超时时间要大于所有分支事务耗时总和 3. 建议在入口Controller方法上声明

五、生产环境优化建议

5.1 参数调优指南

关键server端参数(seata-server/conf/file.conf)

transport {
  thread-factory {
    boss-thread-prefix = "NettyBoss"
    worker-thread-prefix = "NettyServerNIOWorker"
    server-executor-thread-prefix = "NettyServerBizHandler"
    share-boss-worker = false
    client-selector-thread-prefix = "NettyClientSelector"
    client-selector-thread-size = 1
    client-worker-thread-prefix = "NettyClientWorkerThread"
    worker-thread-size = "default"
  }
}

客户端优化建议

seata:
  client:
    rm-report-success-enable: false # 关闭分支执行结果上报
    report-retry-count: 5          # 重试次数

5.2 常见问题排查

全局锁冲突处理: 1. 检查业务SQL条件是否走索引 2. 减少单个事务涉及的数据范围 3. 适当调整隔离级别:

@GlobalTransactional(lockRetryInternal = 100, lockRetryTimes = 30)

事务悬挂问题: - 现象:分支事务先于全局事务注册 - 解决方案:升级到1.5.0+版本,开启:

seata:
  client:
    undo:
      data-validation: true

5.3 监控与告警配置

Prometheus监控配置

metrics {
  enabled = true
  registry-type = "compact"
  exporter-list = "prometheus"
  exporter-prometheus-port = 9898
}

Grafana监控看板: 1. 导入官方Dashboard(ID:10477) 2. 关键监控指标: - seata.transaction.active.count - seata.transaction.committed.rate - seata.transaction.rollback.rate

六、实战案例演示

6.1 电商下单场景

业务流程图

sequenceDiagram
    participant C as Client
    participant O as OrderService
    participant S as StorageService
    participant A as AccountService
    
    C->>O: 提交订单
    O->>S: 扣减库存
    S-->>O: 操作成功
    O->>A: 扣减余额
    A-->>O: 操作成功
    O->>O: 生成订单
    O-->>C: 下单成功

异常处理设计: 1. 库存不足:立即返回错误 2. 余额不足:触发全局回滚 3. 网络超时:依赖重试机制

6.2 跨行转账场景

TCC模式实现

// 转账服务接口
public interface TransferService {
    @TwoPhaseBusinessAction(name = "transfer", commitMethod = "confirm", rollbackMethod = "cancel")
    boolean tryTransfer(@BusinessActionContextParameter(paramName = "from") String from,
                       @BusinessActionContextParameter(paramName = "to") String to,
                       @BusinessActionContextParameter(paramName = "amount") BigDecimal amount);
}

// 账户服务实现
@Service
public class AccountServiceImpl implements AccountService {
    
    @Transactional
    public boolean tryDebit(String accountNo, BigDecimal amount) {
        // 检查账户状态
        // 冻结部分金额
        accountMapper.freezeAmount(accountNo, amount);
        return true;
    }
    
    public boolean confirm(BusinessActionContext context) {
        // 实际扣减冻结金额
        String accountNo = (String)context.getActionContext("from");
        BigDecimal amount = (BigDecimal)context.getActionContext("amount");
        accountMapper.debit(accountNo, amount);
        accountMapper.unfreezeAmount(accountNo, amount);
        return true;
    }
}

SAGA模式设计

// 状态机定义示例
{
  "name": "bankTransferSaga",
  "steps": [
    {
      "name": "deductFromAccount",
      "compensate": "compensateDeduct",
      "service": "accountService",
      "input": ["$.['from']", "$.['amount']"]
    },
    {
      "name": "addToAccount",
      "compensate": "compensateAdd",
      "service": "accountService",
      "input": ["$.['to']", "$.['amount']"]
    }
  ]
}

作者建议:在实际项目中使用Seata时,建议从AT模式开始,随着业务复杂度提升逐步考虑TCC或SAGA模式。同时要特别注意undo_log表的大小控制,建议定期归档历史数据。 “`

推荐阅读:
  1. 如何用Seata解决分布式事务问题
  2. SpringBoot+Dubbo+Seata分布式事务实战

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

seata

上一篇:HashMap 和 HashTable 有什么区别

下一篇:SpringCloud 和SpringBoot 有什么区别

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》