Seata分布式事务实战
Seata分布式事务实战
前言
Seata是阿里巴巴开源的分布式事务解决方案,支持AT、TCC、Saga等多种事务模式。本文将详细介绍Seata的安装配置和AT模式的使用。
一、Seata核心概念
1.1 架构图
┌─────────────────────────────────────────────────────┐ │ Seata Architecture │ │ │ │ ┌──────────────────────────────────────────────┐ │ │ │ TC (Transaction Coordinator) │ │ │ │ Global Session Branch Session Manager │ │ │ └──────────────────────────────────────────────┘ │ │ ▲ ▲ │ │ │ TM │ TM │ │ ┌──────┴──────┐ ┌──────┴──────┐ │ │ │ TM (Transaction Manager) │ │ │ │ │ ┌──────────────────┐ │ │ │ │ │ │ Business Logic │ │ │ │ │ │ └──────────────────┘ │ │ │ │ └────────────────────────┘ │ │ │ │ │ │ ┌──────────────────────────────────────────────┐ │ │ │ RM (Resource Manager) │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ │ │ Order DB │ │ Stock DB │ │ Pay DB │ │ │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ └──────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────┘二、Seata Server配置
2.1 Docker部署
# docker-compose.yml version: '3.8' services: seata: image: seataio/seata-server:1.7.0 container_name: seata-server ports: - "8091:8091" - "7091:7091" environment: - STORE_MODE=db - SEATA_CONFIG_NAME=file:/root/seata-config/registry - SEATA_IP=127.0.0.1 volumes: - ./config:/root/seata-config - seata_data:/root/seata-server/resources depends_on: - mysql mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root_password MYSQL_DATABASE: seata三、AT模式配置
3.1 依赖引入
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata</artifactId> </dependency> <dependency> <groupId>io.seata</groupId> <artifactId>seata-spring-boot-starter</artifactId> </dependency>3.2 应用配置
seata: enabled: true application-id: ${spring.application.name} tx-service-group: my-test-tx-group enable-auto-data-source-proxy: true config: type: nacos nacos: server-addr: ${spring.cloud.nacos.server-addr} namespace: ${spring.cloud.nacos.config.namespace:} group: SEATA_GROUP >@Service @Slf4j public class OrderServiceImpl implements OrderService { @GlobalTransactional(name = "create-order", rollbackFor = Exception.class) @Override public OrderDTO createOrder(CreateOrderRequest request) { log.info("Creating order: {}", request); // 1. 创建订单 Order order = createLocalOrder(request); // 2. 扣减库存(远程调用) boolean stockReduced = inventoryClient.reduceStock( request.getProductId(), request.getQuantity() ); if (!stockReduced) { throw new BusinessException("Stock reduction failed"); } // 3. 扣减余额(远程调用) boolean balanceDeducted = accountClient.deductBalance( request.getUserId(), request.getAmount() ); if (!balanceDeducted) { throw new BusinessException("Balance deduction failed"); } return orderMapper.toDTO(order); } @Transactional public Order createLocalOrder(CreateOrderRequest request) { Order order = new Order(); order.setOrderNumber(generateOrderNumber()); order.setUserId(request.getUserId()); order.setProductId(request.getProductId()); order.setQuantity(request.getQuantity()); order.setAmount(request.getAmount()); order.setStatus(OrderStatus.PENDING); return orderRepository.save(order); } }4.2 事务传播
@Service public class OrderServiceImpl { @GlobalTransactional(name = "outer-transaction") public void outerTransaction() { // 外层事务 createOrder(); // 嵌套事务(自动加入外层事务) nestedTransaction(); } @Transactional(propagation = Propagation.REQUIRES_NEW) public void nestedTransaction() { // 独立事务 doSomething(); } }五、TCC模式配置
5.1 TCC接口定义
@LocalTCC public interface InventoryTccService { @TwoPhaseBusinessAction( name = "prepareInventory", commitMethod = "commit", rollbackMethod = "rollback" ) boolean prepare( BusinessActionContext actionContext, @BusinessActionContextParameter(paramName = "productId") Long productId, @BusinessActionContextParameter(paramName = "quantity") Integer quantity ); boolean commit(BusinessActionContext actionContext); boolean rollback(BusinessActionContext actionContext); } @Service @Slf4j public class InventoryTccServiceImpl implements InventoryTccService { @Override @Transactional public boolean prepare(BusinessActionContext actionContext, Long productId, Integer quantity) { log.info("TCC Prepare: productId={}, quantity={}", productId, quantity); // 预扣减库存 return inventoryRepository.reserveStock(productId, quantity); } @Override @Transactional public boolean commit(BusinessActionContext actionContext) { log.info("TCC Commit"); // 确认扣减 Long productId = (Long) actionContext.getActionContext("productId"); Integer quantity = (Integer) actionContext.getActionContext("quantity"); inventoryRepository.confirmStock(productId, quantity); return true; } @Override @Transactional public boolean rollback(BusinessActionContext actionContext) { log.info("TCC Rollback"); // 释放库存 Long productId = (Long) actionContext.getActionContext("productId"); Integer quantity = (Integer) actionContext.getActionContext("quantity"); inventoryRepository.releaseStock(productId, quantity); return true; } }5.2 TCC调用
@Service public class OrderService { @Autowired private InventoryTccService inventoryTccService; @GlobalTransactional(name = "create-order-tcc") public void createOrderWithTcc(CreateOrderRequest request) { // 订单创建逻辑... // TCC调用 boolean reserved = inventoryTccService.prepare( new BusinessActionContext(), request.getProductId(), request.getQuantity() ); if (!reserved) { throw new BusinessException("Stock reservation failed"); } } }六、总结
Seata提供了完善的分布式事务解决方案,AT模式对业务代码零侵入,适合大多数场景;TCC模式性能更高,适合对性能有较高要求的场景。
