Spring Boot 3.x分布式事务实战:Seata AT模式配置与生产部署全指南

分布式事务为什么选Seata AT模式

微服务架构下,一次业务操作可能涉及多个服务的本地事务。比如电商下单:订单服务创建订单、库存服务扣减库存、账户服务扣减余额,三者必须原子性完成。网络故障或服务异常导致部分成功部分失败时,数据就不一致了。

Seata的AT(Automatic Transaction)模式对业务代码侵入最小——只需加一个@GlobalTransactional注解,框架自动处理两阶段提交的回滚逻辑。相比TCC模式需要编写Try/Confirm/Cancel三个方法,AT模式通过拦截SQL自动生成回滚日志,开发效率高出数倍。

AT模式的代价是性能:一阶段提交时需要生成undo_log,二阶段回滚时需要反向补偿。对于高并发场景,这个开销需要评估。

Seata Server部署与配置

Seata 1.8+推荐使用TC(Transaction Coordinator)独立部署模式:

# 下载Seata Server
wget https://github.com/seata/seata/releases/download/v2.0.0/seata-server-2.0.0.tar.gz
tar -xzf seata-server-2.0.0.tar.gz

application.yml核心配置(以Nacos为注册中心,MySQL为存储):

seata:
  server:
    service-port: 8091
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: seata
      group: DEFAULT_GROUP
      application: seata-server
  store:
    mode: db
    db:
      datasource: druid
      db-type: mysql
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true
      user: seata
      password: seata_pwd
      min-conn: 5
      max-conn: 30
      global-table: global_table
      branch-table: branch_table
      lock-table: lock_table
      distributed-lock-table: distributed_lock

初始化Seata数据库表:

-- global_table: 全局事务表
CREATE TABLE global_table (
  xid VARCHAR(128) PRIMARY KEY,
  transaction_id BIGINT,
  status TINYINT NOT NULL,
  application_id VARCHAR(32),
  transaction_service_id VARCHAR(32),
  transaction_name VARCHAR(128),
  timeout INT,
  begin_time BIGINT,
  application_data VARCHAR(2000),
  gmt_create TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  gmt_modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- branch_table: 分支事务表
CREATE TABLE 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 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  gmt_modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (branch_id, xid)
);

-- lock_table: 全局锁表
CREATE TABLE lock_table (
  row_key VARCHAR(128) NOT NULL,
  xid VARCHAR(128),
  transaction_id BIGINT,
  branch_id BIGINT NOT NULL,
  resource_id VARCHAR(256),
  table_name VARCHAR(32),
  pk VARCHAR(36),
  status TINYINT NOT NULL DEFAULT 0,
  gmt_create TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  gmt_modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (row_key, branch_id)
);

Spring Boot微服务端集成

每个参与分布式事务的微服务都需要配置Seata客户端。以Maven依赖为例:

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

客户端application.yml配置:

seata:
  enabled: true
  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
      namespace: seata
      group: DEFAULT_GROUP
      application: seata-server

每个微服务的业务数据库中需要undo_log表:

CREATE TABLE undo_log (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  branch_id BIGINT NOT NULL,
  xid VARCHAR(128) NOT NULL,
  context VARCHAR(128) NOT NULL,
  rollback_info LONGBLOB NOT NULL,
  log_status INT NOT NULL,
  log_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  log_modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY ux_undo_log (xid, branch_id)
);

业务代码实现分布式事务

订单服务——事务发起方:

@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private InventoryClient inventoryClient;

    @Autowired
    private AccountClient accountClient;

    @GlobalTransactional(name = "create-order", timeoutMills = 60000)
    public Order createOrder(OrderDTO dto) {
        // 1. 创建订单(本地事务)
        Order order = new Order();
        order.setUserId(dto.getUserId());
        order.setProductId(dto.getProductId());
        order.setAmount(dto.getAmount());
        order.setStatus("CREATED");
        orderMapper.insert(order);

        // 2. 扣减库存(远程调用)
        inventoryClient.deduct(dto.getProductId(), dto.getQuantity());

        // 3. 扣减账户余额(远程调用)
        accountClient.debit(dto.getUserId(), dto.getAmount());

        return order;
    }
}

库存服务——事务参与方,无需额外注解:

@Service
public class InventoryService {

    @Autowired
    private InventoryMapper inventoryMapper;

    @Transactional  // 本地事务即可,Seata AT模式自动纳入全局事务
    public void deduct(String productId, int quantity) {
        Inventory inv = inventoryMapper.selectByProductId(productId);
        if (inv.getStock() < quantity) {
            throw new BusinessException("库存不足");
        }
        inv.setStock(inv.getStock() - quantity);
        inventoryMapper.updateById(inv);
    }
}

如果步骤3(扣减余额)抛出异常,Seata会自动回滚步骤1和步骤2。回滚原理是:一阶段提交时,Seata拦截SQL并记录修改前的数据到undo_log,回滚时读取undo_log执行反向SQL。

生产环境关键调优

全局事务超时:默认60秒。跨服务调用链较长时,合理设置timeoutMills。超时后Seata自动回滚,业务侧要做好超时异常处理。

全局锁超时:当两个全局事务操作同一行数据时,后到的事务会等待全局锁。默认30秒获取不到锁就抛出LockConflictException。高并发场景下调低重试间隔:

seata:
  client:
    rm:
      lock:
        retry-interval: 10    # 锁重试间隔10ms
        retry-times: 30       # 重试30次
      async-commit-buffer-limit: 10000

undo_log清理:二阶段完成后的undo_log不会自动删除。配置定时清理任务:

@Scheduled(cron = "0 0 3 * * ?")
public void cleanUndoLog() {
    undoLogMapper.deleteByStatusAndGmtModified(
        TransactionStatus.Finished.getCode(),
        LocalDateTime.now().minusDays(7)
    );
}

Seata Server高可用:至少部署3个TC实例,通过Nacos注册中心实现服务发现。TC实例无状态,global_table中的数据是共享的,任一实例故障不影响全局事务的提交和回滚。

常见异常与排查

Could not found global transaction xid:XID未传递到下游服务。检查SeataFilter是否注册,Feign/RestTemplate拦截器是否配置。Spring Cloud 2021+需要手动注册SeataFeignClientAutoConfiguration。

LockConflictException:全局锁冲突。两个事务竞争同一行数据。业务上应该避免热点数据的高并发写,或改用TCC模式在Try阶段预留资源。

RollbackFailedException:回滚失败,undo_log已被清理或数据已被手动修改。这种情况下需要人工介入,根据业务日志补齐数据。

Seata AT模式在中小规模业务中足够实用,核心优势是低侵入性。但万级TPS场景下,undo_log写入和全局锁等待会成为瓶颈,那时需要考虑TCC或Saga模式,将补偿逻辑的细粒度控制权交给开发者。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/springboot3x-fen-bu-shi-shi-wu-shi-zhan-seataat-mo-shi-pei/

(0)
小编小编
上一篇 2026年7月28日
下一篇 2026年7月28日

相关推荐

Spring Boot 3.x分布式事务实战:Seata AT模式配置与生产部署全指南

分布式事务为什么选Seata AT模式

微服务架构下,一次业务操作可能涉及多个服务的本地事务。比如电商下单:订单服务创建订单、库存服务扣减库存、账户服务扣减余额,三者必须原子性完成。网络故障或服务异常导致部分成功部分失败时,数据就不一致了。

Seata的AT(Automatic Transaction)模式对业务代码侵入最小——只需加一个@GlobalTransactional注解,框架自动处理两阶段提交的回滚逻辑。相比TCC模式需要编写Try/Confirm/Cancel三个方法,AT模式通过拦截SQL自动生成回滚日志,开发效率高出数倍。

AT模式的代价是性能:一阶段提交时需要生成undo_log,二阶段回滚时需要反向补偿。对于高并发场景,这个开销需要评估。

Seata Server部署与配置

Seata 1.8+推荐使用TC(Transaction Coordinator)独立部署模式:

# 下载Seata Server
wget https://github.com/seata/seata/releases/download/v2.0.0/seata-server-2.0.0.tar.gz
tar -xzf seata-server-2.0.0.tar.gz

application.yml核心配置(以Nacos为注册中心,MySQL为存储):

seata:
  server:
    service-port: 8091
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: seata
      group: DEFAULT_GROUP
      application: seata-server
  store:
    mode: db
    db:
      datasource: druid
      db-type: mysql
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true
      user: seata
      password: seata_pwd
      min-conn: 5
      max-conn: 30
      global-table: global_table
      branch-table: branch_table
      lock-table: lock_table
      distributed-lock-table: distributed_lock

初始化Seata数据库表:

-- global_table: 全局事务表
CREATE TABLE global_table (
  xid VARCHAR(128) PRIMARY KEY,
  transaction_id BIGINT,
  status TINYINT NOT NULL,
  application_id VARCHAR(32),
  transaction_service_id VARCHAR(32),
  transaction_name VARCHAR(128),
  timeout INT,
  begin_time BIGINT,
  application_data VARCHAR(2000),
  gmt_create TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  gmt_modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- branch_table: 分支事务表
CREATE TABLE 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 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  gmt_modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (branch_id, xid)
);

-- lock_table: 全局锁表
CREATE TABLE lock_table (
  row_key VARCHAR(128) NOT NULL,
  xid VARCHAR(128),
  transaction_id BIGINT,
  branch_id BIGINT NOT NULL,
  resource_id VARCHAR(256),
  table_name VARCHAR(32),
  pk VARCHAR(36),
  status TINYINT NOT NULL DEFAULT 0,
  gmt_create TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  gmt_modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (row_key, branch_id)
);

Spring Boot微服务端集成

每个参与分布式事务的微服务都需要配置Seata客户端。以Maven依赖为例:

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

客户端application.yml配置:

seata:
  enabled: true
  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
      namespace: seata
      group: DEFAULT_GROUP
      application: seata-server

每个微服务的业务数据库中需要undo_log表:

CREATE TABLE undo_log (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  branch_id BIGINT NOT NULL,
  xid VARCHAR(128) NOT NULL,
  context VARCHAR(128) NOT NULL,
  rollback_info LONGBLOB NOT NULL,
  log_status INT NOT NULL,
  log_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  log_modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY ux_undo_log (xid, branch_id)
);

业务代码实现分布式事务

订单服务——事务发起方:

@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private InventoryClient inventoryClient;

    @Autowired
    private AccountClient accountClient;

    @GlobalTransactional(name = "create-order", timeoutMills = 60000)
    public Order createOrder(OrderDTO dto) {
        // 1. 创建订单(本地事务)
        Order order = new Order();
        order.setUserId(dto.getUserId());
        order.setProductId(dto.getProductId());
        order.setAmount(dto.getAmount());
        order.setStatus("CREATED");
        orderMapper.insert(order);

        // 2. 扣减库存(远程调用)
        inventoryClient.deduct(dto.getProductId(), dto.getQuantity());

        // 3. 扣减账户余额(远程调用)
        accountClient.debit(dto.getUserId(), dto.getAmount());

        return order;
    }
}

库存服务——事务参与方,无需额外注解:

@Service
public class InventoryService {

    @Autowired
    private InventoryMapper inventoryMapper;

    @Transactional  // 本地事务即可,Seata AT模式自动纳入全局事务
    public void deduct(String productId, int quantity) {
        Inventory inv = inventoryMapper.selectByProductId(productId);
        if (inv.getStock() < quantity) {
            throw new BusinessException("库存不足");
        }
        inv.setStock(inv.getStock() - quantity);
        inventoryMapper.updateById(inv);
    }
}

如果步骤3(扣减余额)抛出异常,Seata会自动回滚步骤1和步骤2。回滚原理是:一阶段提交时,Seata拦截SQL并记录修改前的数据到undo_log,回滚时读取undo_log执行反向SQL。

生产环境关键调优

全局事务超时:默认60秒。跨服务调用链较长时,合理设置timeoutMills。超时后Seata自动回滚,业务侧要做好超时异常处理。

全局锁超时:当两个全局事务操作同一行数据时,后到的事务会等待全局锁。默认30秒获取不到锁就抛出LockConflictException。高并发场景下调低重试间隔:

seata:
  client:
    rm:
      lock:
        retry-interval: 10    # 锁重试间隔10ms
        retry-times: 30       # 重试30次
      async-commit-buffer-limit: 10000

undo_log清理:二阶段完成后的undo_log不会自动删除。配置定时清理任务:

@Scheduled(cron = "0 0 3 * * ?")
public void cleanUndoLog() {
    undoLogMapper.deleteByStatusAndGmtModified(
        TransactionStatus.Finished.getCode(),
        LocalDateTime.now().minusDays(7)
    );
}

Seata Server高可用:至少部署3个TC实例,通过Nacos注册中心实现服务发现。TC实例无状态,global_table中的数据是共享的,任一实例故障不影响全局事务的提交和回滚。

常见异常与排查

Could not found global transaction xid:XID未传递到下游服务。检查SeataFilter是否注册,Feign/RestTemplate拦截器是否配置。Spring Cloud 2021+需要手动注册SeataFeignClientAutoConfiguration。

LockConflictException:全局锁冲突。两个事务竞争同一行数据。业务上应该避免热点数据的高并发写,或改用TCC模式在Try阶段预留资源。

RollbackFailedException:回滚失败,undo_log已被清理或数据已被手动修改。这种情况下需要人工介入,根据业务日志补齐数据。

Seata AT模式在中小规模业务中足够实用,核心优势是低侵入性。但万级TPS场景下,undo_log写入和全局锁等待会成为瓶颈,那时需要考虑TCC或Saga模式,将补偿逻辑的细粒度控制权交给开发者。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/springboot3x-fen-bu-shi-shi-wu-shi-zhan-seataat-mo-shi-pei/

(0)
小编小编
上一篇 2026年7月28日
下一篇 2026年7月28日

相关推荐

Spring Boot 3.x分布式事务实战:Seata AT模式配置与消息最终一致性方案选型

微服务拆分后的事务困境

单体应用中一个本地事务就能保证的数据一致性,在微服务架构下变成了跨库、跨服务的分布式事务问题。典型场景:订单服务创建订单后需要调用库存服务扣减库存、调用支付服务冻结资金,任何一个环节失败都需要回滚已执行的操作。Spring Boot 3.x生态下,Seata的AT模式提供了对业务代码侵入最低的方案,而基于消息队列的最终一致性方案则适合对实时性要求不高的场景。两种方案的选型和配置细节差异较大,本文逐项拆解。

Seata AT模式原理与Spring Boot 3.x集成

AT模式的核心是两阶段提交的自动化。一阶段拦截业务SQL,生成前镜像(Before Image)和后镜像(After Image)存入undo_log表,同时获取全局锁;二阶段提交则异步清理undo_log,回滚则用前镜像做补偿。业务代码只需要加一个@GlobalTransactional注解。

Seata Server部署(2.2.0版本):

# docker-compose.yml
version: '3.8'
services:
  seata-server:
    image: seataio/seata-server:2.2.0
    ports:
      - "8091:8091"
      - "7091:7091"
    environment:
      - SEATA_IP=seata-server
      - STORE_MODE=db
    volumes:
      - ./seata-config:/seata-server/resources

Spring Boot 3.x客户端配置:

// pom.xml
<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>2.2.0</version>
</dependency>

// application.yml
seata:
  enabled: true
  application-id: order-service
  tx-service-group: my-tx-group
  service:
    vgroup-mapping:
      my-tx-group: default
  registry:
    type: nacos
    nacos:
      server-addr: nacos:8848
      namespace: seata
      group: SEATA_GROUP
  config:
    type: nacos
    nacos:
      server-addr: nacos:8848
      namespace: seata

每个参与分布式事务的数据库需要创建undo_log表:

-- undo_log 建表语句(MySQL)
CREATE TABLE IF NOT EXISTS undo_log (
    id            BIGINT       NOT NULL AUTO_INCREMENT,
    branch_id     BIGINT       NOT NULL,
    xid           VARCHAR(128) NOT NULL,
    context       VARCHAR(128) NOT NULL,
    rollback_info LONGBLOB     NOT NULL,
    log_status    INT          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 DEFAULT CHARSET=utf8mb4;

业务代码实战:订单-库存-支付三服务联动

订单服务中,业务入口加@GlobalTransactional注解:

@Service
@Slf4j
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private InventoryClient inventoryClient;
    @Autowired
    private PaymentClient paymentClient;

    @GlobalTransactional(name = "create-order", rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    public OrderDTO createOrder(CreateOrderRequest request) {
        // 1. 创建订单
        Order order = new Order();
        order.setUserId(request.getUserId());
        order.setProductId(request.getProductId());
        order.setQuantity(request.getQuantity());
        order.setAmount(request.getAmount());
        order.setStatus(OrderStatus.CREATED);
        orderMapper.insert(order);
        log.info("订单创建成功, orderId={}", order.getId());

        // 2. 扣减库存(远程调用)
        inventoryClient.deduct(request.getProductId(), request.getQuantity());
        log.info("库存扣减成功");

        // 3. 冻结资金(远程调用)
        paymentClient.freeze(request.getUserId(), request.getAmount());
        log.info("资金冻结成功");

        return OrderDTO.fromEntity(order);
    }
}

库存服务和支付服务的扣减/冻结方法同样需要加@Transactional注解。Seata AT模式通过DataSource代理自动拦截SQL,生成undo_log,无需业务代码手动处理回滚。当任何环节抛出异常,Seata协调器自动调用各分支的undo逻辑做补偿。

消息最终一致性方案:本地消息表+RocketMQ

AT模式虽然代码侵入低,但全局锁机制在高并发场景下会成为瓶颈。对实时性要求不严格的场景,本地消息表+消息队列的最终一致性方案更合适。核心思路:业务操作和消息记录在同一个本地事务中写入,后台定时任务扫描消息表并投递到MQ。

@Service
public class OrderServiceV2 {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OutboxMessageMapper outboxMapper;

    @Transactional(rollbackFor = Exception.class)
    public OrderDTO createOrderWithOutbox(CreateOrderRequest request) {
        // 1. 创建订单
        Order order = new Order();
        order.setUserId(request.getUserId());
        order.setProductId(request.getProductId());
        order.setQuantity(request.getQuantity());
        order.setAmount(request.getAmount());
        order.setStatus(OrderStatus.CREATED);
        orderMapper.insert(order);

        // 2. 写入本地消息表(同一事务)
        OutboxMessage msg = new OutboxMessage();
        msg.setTopic("order-created");
        msg.setKey(String.valueOf(order.getId()));
        msg.setBody(JSON.toJSONString(new OrderEvent(order)));
        msg.setStatus(OutboxStatus.PENDING);
        msg.setRetryCount(0);
        msg.setNextRetryAt(LocalDateTime.now());
        outboxMapper.insert(msg);

        return OrderDTO.fromEntity(order);
    }
}

消息投递调度器:

@Component
@Slf4j
public class OutboxMessageScheduler {

    @Autowired
    private OutboxMessageMapper outboxMapper;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Scheduled(fixedDelay = 5000) // 每5秒扫描
    @Transactional
    public void sendPendingMessages() {
        List<OutboxMessage> messages = outboxMapper.selectPending(
            OutboxStatus.PENDING,
            LocalDateTime.now(),
            50  // 每批最多50条
        );

        for (OutboxMessage msg : messages) {
            try {
                SendResult result = rocketMQTemplate.syncSend(
                    msg.getTopic(),
                    MessageBuilder.withPayload(msg.getBody())
                        .setKeys(msg.getKey())
                        .build(),
                    3000  // 超时3秒
                );
                if (result.getSendStatus() == SendStatus.SEND_OK) {
                    msg.setStatus(OutboxStatus.SENT);
                    outboxMapper.updateById(msg);
                }
            } catch (Exception e) {
                msg.setRetryCount(msg.getRetryCount() + 1);
                if (msg.getRetryCount() >= 5) {
                    msg.setStatus(OutboxStatus.FAILED);
                    log.error("消息投递失败5次,标记为FAILED, id={}", msg.getId());
                } else {
                    // 指数退避
                    msg.setNextRetryAt(LocalDateTime.now().plusMinutes(
                        (long) Math.pow(2, msg.getRetryCount())
                    ));
                }
                outboxMapper.updateById(msg);
            }
        }
    }
}

两种方案选型对比

维度 Seata AT模式 本地消息表+MQ
一致性保证 强一致(同步回滚) 最终一致(异步补偿)
代码侵入 低(注解驱动) 中(需消息表+调度)
性能 全局锁竞争下吞吐受限 无锁,吞吐高
适用场景 资金、库存等强一致需求 通知、日志等可延迟场景
故障恢复 Seata Server自动回滚 消息重试+人工补偿

实际项目中两种方案通常并存:核心交易链路用Seata AT保证强一致,非核心的异步通知、数据同步等用消息最终一致性方案。关键是根据业务SLA明确每种场景的一致性需求,不要一刀切。

Seata生产环境踩坑记录

坑1:全局锁超时。默认全局锁超时60秒,长事务容易超时。调大lock-retry-times和lock-retry-interval:seata.client.lock.retry-times=30, seata.client.lock.retry-interval=10。

坑2:undo_log序列化兼容。字段增删改后,旧undo_log反序列化失败。上线时先禁用分布式事务,手动清理undo_log后再启用。或配置jackson序列化忽略未知属性。

坑3:Seata Server单点故障。生产环境至少部署3个Seata Server节点,使用Nacos做注册中心和配置中心,数据库存储Transaction日志。Seata Server本身无状态,任意节点宕机不影响运行中的全局事务。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/springboot3x-fen-bu-shi-shi-wu-shi-zhan-seataat-mo-shi-pei/

(0)
小编小编
上一篇 2026年7月23日
下一篇 2026年7月23日

相关推荐