← 返回首页
🔄

分布式事务详解:Seata与TCC

📂 java ⏱ 2 min 243 words

分布式事务详解:Seata与TCC

概述

分布式事务是分布式系统中的重要问题。本教程介绍Seata和TCC模式的使用。

1. Seata

import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.stereotype.Service;

@Service
public class OrderService {
    @GlobalTransactional
    public void createOrder(Order order) {
        // 创建订单
        orderRepository.save(order);
        
        // 扣减库存
        inventoryService.deduct(order.getItems());
        
        // 扣减余额
        accountService.deduct(order.getUserId(), order.getTotalAmount());
    }
}

// 配置
# application.yml
spring:
  cloud:
    alibaba:
      seata:
        enabled: true
        tx-service-group: my_test_tx_group

# seata.conf
[service]
vgroupMapping.my_test_tx_group = default
[client]
rm.asyncCommitBufferLimit = 10000

2. TCC模式

// Try阶段:预留资源
// Confirm阶段:确认提交
// Cancel阶段:取消预留

@Component
public class AccountTccService {
    @TwoPhaseBusinessAction(name = "prepareDeduct", commitMethod = "confirm", rollbackMethod = "cancel")
    public boolean prepare(BusinessActionContext context, @BusinessActionContextParameter(paramName = "userId") String userId, @BusinessActionContextParameter(paramName = "amount") double amount) {
        // 预留余额
        accountRepository.freeze(userId, amount);
        return true;
    }
    
    public boolean confirm(BusinessActionContext context) {
        String userId = (String) context.getActionContext("userId");
        double amount = (Double) context.getActionContext("amount");
        
        // 确认扣减
        accountRepository.deduct(userId, amount);
        accountRepository.unfreeze(userId, amount);
        return true;
    }
    
    public boolean cancel(BusinessActionContext context) {
        String userId = (String) context.getActionContext("userId");
        double amount = (Double) context.getActionContext("amount");
        
        // 取消预留
        accountRepository.unfreeze(userId, amount);
        return true;
    }
}

3. 实际应用示例

订单创建

@Service
public class OrderService {
    @GlobalTransactional
    public Order createOrder(CreateOrderRequest request) {
        // 1. 创建订单
        Order order = new Order(request);
        orderRepository.save(order);
        
        // 2. 扣减库存
        inventoryService.deduct(request.getItems());
        
        // 3. 扣减余额
        accountService.deduct(request.getUserId(), order.getTotalAmount());
        
        // 4. 发布订单创建事件
        eventPublisher.publish(new OrderCreatedEvent(order));
        
        return order;
    }
}

库存扣减

@Service
public class InventoryService {
    @GlobalTransactional
    public void deduct(List<OrderItem> items) {
        for (OrderItem item : items) {
            // 检查库存
            Inventory inventory = inventoryRepository.findByProductId(item.getProductId());
            if (inventory.getQuantity() < item.getQuantity()) {
                throw new InsufficientStockException("库存不足");
            }
            
            // 扣减库存
            inventory.setQuantity(inventory.getQuantity() - item.getQuantity());
            inventoryRepository.save(inventory);
        }
    }
}

4. 最佳实践

  1. 选择合适的方案:Seata简单,TCC灵活
  2. 设计补偿逻辑:确保事务的最终一致性
  3. 处理异常情况:确保事务的正确回滚
  4. 监控事务状态:实时监控分布式事务状态
  5. 测试事务功能:确保分布式事务正常工作

总结

分布式事务是分布式系统中的重要问题。掌握Seata和TCC模式的使用,可以解决分布式系统中的事务一致性问题。