分布式事务详解:Seata与TCC
分布式事务详解: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. 最佳实践
- 选择合适的方案:Seata简单,TCC灵活
- 设计补偿逻辑:确保事务的最终一致性
- 处理异常情况:确保事务的正确回滚
- 监控事务状态:实时监控分布式事务状态
- 测试事务功能:确保分布式事务正常工作
总结
分布式事务是分布式系统中的重要问题。掌握Seata和TCC模式的使用,可以解决分布式系统中的事务一致性问题。