Spring Boot微服务架构下的分布式事务解决方案与实战配置

微服务拆分后的事务一致性挑战

单体应用拆分为微服务后,原本一个数据库事务就能搞定的业务操作,现在跨越多个服务,每个服务独占自己的数据库实例。下单流程就是典型案例:订单服务创建订单、库存服务扣减库存、支付服务冻结资金——三步操作分布在三个独立的数据库中,任何一步失败都需要全部回滚。

分布式事务的核心矛盾是:CAP定理下,高可用与强一致性无法同时保证。工程实践中选择哪种方案,取决于业务对一致性等级的要求:

// 一致性等级与适用场景
强一致性(2PC/XA)  → 资金交易、库存扣减
最终一致性(TCC/Saga)→ 订单流程、业务中台
弱一致性(最大努力通知)→ 日志采集、通知推送

Seata AT模式:低侵入式分布式事务

Seata的AT模式(Auto Transaction)是Java生态中最落地的方案,对业务代码侵入最小——只需要在发起方方法上加一个@GlobalTransactional注解。

// Seata AT模式配置
// 1. 引入依赖(Spring Boot 3.2+ / JDK 17)
// pom.xml
<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>1.8.0</version>
</dependency>
<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-all</artifactId>
    <version>1.8.0</version>
</dependency>

// 2. 配置Seata数据源代理
@Configuration
public class SeataDataSourceConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.hikari")
    public DataSource dataSource() {
        return new HikariDataSource();
    }

    @Bean
    @Primary
    public DataSourceProxy dataSourceProxy(DataSource dataSource) {
        return new DataSourceProxy(dataSource);
    }
}

// 3. 业务代码 - 订单服务(事务发起方)
@Service
public class OrderService {

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

    @GlobalTransactional(timeoutMills = 30000, name = "create-order")
    public OrderResult createOrder(CreateOrderRequest request) {
        // 1. 创建订单(本地事务,Seata自动生成undo_log)
        Order order = new Order();
        order.setUserId(request.getUserId());
        order.setProductId(request.getProductId());
        order.setQuantity(request.getQuantity());
        order.setStatus(OrderStatus.INIT);
        orderMapper.insert(order);

        // 2. 扣减库存(远程调用)
        InventoryResult invResult = inventoryClient.deduct(
            request.getProductId(), request.getQuantity()
        );
        if (!invResult.isSuccess()) {
            throw new BusinessException("库存不足");
        }

        // 3. 冻结资金(远程调用)
        PaymentResult payResult = paymentClient.freeze(
            request.getUserId(), order.getTotalAmount()
        );
        if (!payResult.isSuccess()) {
            throw new BusinessException("余额不足");
        }

        order.setStatus(OrderStatus.CREATED);
        orderMapper.updateById(order);
        return OrderResult.success(order);
    }
}

AT模式的工作原理:Seata在SQL执行前自动生成前镜像(before-image),执行后生成后镜像(after-image),写入undo_log表。回滚时根据前镜像反向补偿。全局事务提交时异步清理undo_log。

Saga模式:长流程业务编排方案

AT模式适合执行时间短(秒级)的分布式事务。对于执行时间长的业务流程(如供应商发货、物流签收),Saga模式更合适——它不锁资源,通过正向执行+反向补偿来保证最终一致性。

// Seata Saga状态机定义
// resources/saga/create-order.json
{
  "Name": "createOrder",
  "Comment": "订单创建Saga流程",
  "StartState": "CreateOrder",
  "States": {
    "CreateOrder": {
      "Type": "ServiceTask",
      "ServiceName": "orderService",
      "ServiceMethod": "create",
      "CompensateMethod": "cancel",
      "Next": "DeductInventory",
      "Input": ["$.request"]
    },
    "DeductInventory": {
      "Type": "ServiceTask",
      "ServiceName": "inventoryService",
      "ServiceMethod": "deduct",
      "CompensateMethod": "restore",
      "Next": "FreezePayment",
      "Input": ["$.request.productId", "$.request.quantity"]
    },
    "FreezePayment": {
      "Type": "ServiceTask",
      "ServiceName": "paymentService",
      "ServiceMethod": "freeze",
      "CompensateMethod": "unfreeze",
      "Next": "Succeed",
      "Input": ["$.request.userId", "$.createOrder.totalAmount"]
    },
    "Succeed": {
      "Type": "Succeed"
    }
  }
}

消息中间件实现最终一致性

RocketMQ事务消息是另一种分布式事务实现路径——不需要引入Seata这样的独立事务协调器,直接复用消息中间件做事务保障。

// RocketMQ事务消息生产者
@Component
public class OrderTransactionProducer {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    public void sendOrderTransaction(Order order) {
        rocketMQTemplate.sendMessageInTransaction(
            "order-topic",
            MessageBuilder.withPayload(order)
                .setHeader("orderId", order.getId())
                .build(),
            order  // 传递给本地事务的参数
        );
    }

    // 本地事务执行器
    @RocketMQTransactionListener
    static class OrderTransactionListener implements RocketMQLocalTransactionListener {

        @Autowired
        private OrderService orderService;

        @Override
        public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
            try {
                Order order = (Order) arg;
                orderService.createOrder(order);
                return RocketMQLocalTransactionState.COMMIT;
            } catch (Exception e) {
                return RocketMQLocalTransactionState.ROLLBACK;
            }
        }

        @Override
        public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
            String orderId = (String) msg.getHeaders().get("orderId");
            Order order = orderService.getById(orderId);
            if (order != null && order.getStatus() == OrderStatus.CREATED) {
                return RocketMQLocalTransactionState.COMMIT;
            }
            return RocketMQLocalTransactionState.ROLLBACK;
        }
    }
}

服务治理与API接口规范

分布式事务引入后,服务间调用关系的治理变得更重要。Sentinel做限流熔断、Nacos做服务注册发现、SkyWalking做链路追踪——这三件套是微服务治理的基础设施。关键配置:

// Sentinel限流规则(针对库存服务)
@SentinelResource(value = "deduct-inventory",
    blockHandler = "handleBlock",
    fallback = "handleFallback")
public InventoryResult deduct(String productId, int quantity) {
    return inventoryService.deduct(productId, quantity);
}

public InventoryResult handleBlock(String productId, int quantity, BlockException ex) {
    log.warn("库存扣减被限流: product={}", productId);
    return InventoryResult.fail("系统繁忙,请稍后重试");
}

public InventoryResult handleFallback(String productId, int quantity, Throwable ex) {
    log.error("库存扣降级: product={}, error={}", productId, ex.getMessage());
    return InventoryResult.fail("服务暂时不可用");
}

业务中台建设中,分布式事务是技术架构的”承重墙”。选型时记住一个原则:能不用分布式事务就不用——通过业务流程重组(将跨服务操作合并为单服务内的本地事务)避免分布式事务,永远是成本最低的方案。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/springboot-wei-fu-wu-jia-gou-xia-de-fen-bu-shi-shi-wu-jie/

(0)
小编小编
上一篇 1天前
下一篇 1天前

相关推荐