Spring Cloud + FeignClient 实现 TCC 分布式事务
文章目录
背景
面试一些候选人时候大多会说自己用过分布式事务,而且大多是使用Seta这个框架。但问题避免全局锁的时候大多会说自己使用了TCC这种模式。
但实际上大多候选人并没有真正实现过TCC分布式事务,问到一些细节时候就答不上来。
所以这里就简单实现一个基于Spring Cloud + Feign的TCC分布式事务,以便面试的后续人有资料可以搜索到。
架构
假设有两个微服务:
OrderService:负责创建订单
InventoryService:负责扣减库存(Feign RPC 被调用方)
整体流程如下:
OrderService (TCC协调者)
|
├── Try 阶段: 调用 InventoryService.tryReserve()
├── Confirm 阶段: 调用 InventoryService.confirmReserve()
└── Cancel 阶段: 调用 InventoryService.cancelReserve()
FeignClient 定义
@FeignClient(name = "inventory-service", path = "/inventory")
public interface InventoryServiceFeign {
@PostMapping("/tryReserve")
R<Boolean> tryReserve(@RequestBody InventoryTryDTO dto);
@PostMapping("/confirmReserve")
R<Boolean> confirmReserve(@RequestBody InventoryConfirmDTO dto);
@PostMapping("/cancelReserve")
R<Boolean> cancelReserve(@RequestBody InventoryCancelDTO dto);
}
服务端实现
@RestController
@RequestMapping("/inventory")
public class InventoryController {
@Autowired
private InventoryService inventoryService;
@PostMapping("/tryReserve")
public R<Boolean> tryReserve(@RequestBody InventoryTryDTO dto) {
return R.ok(inventoryService.tryReserve(dto));
}
@PostMapping("/confirmReserve")
public R<Boolean> confirmReserve(@RequestBody InventoryConfirmDTO dto) {
return R.ok(inventoryService.confirmReserve(dto));
}
@PostMapping("/cancelReserve")
public R<Boolean> cancelReserve(@RequestBody InventoryCancelDTO dto) {
return R.ok(inventoryService.cancelReserve(dto));
}
}
Service层伪代码
@Service
public class InventoryService {
// Try:冻结库存
public boolean tryReserve(InventoryTryDTO dto) {
// 检查库存是否足够
// 若足够 -> 记录冻结记录 (state=TRY)
// 库存临时锁定 / 扣减冻结量
return true;
}
// Confirm:正式扣减
public boolean confirmReserve(InventoryConfirmDTO dto) {
// 查找冻结记录 (state=TRY)
// 扣减实际库存,删除冻结记录
return true;
}
// Cancel:取消冻结
public boolean cancelReserve(InventoryCancelDTO dto) {
// 查找冻结记录 (state=TRY)
// 释放冻结库存
return true;
}
}
OrderService 实现(TCC 协调者)
@Service
public class OrderService {
@Autowired
private InventoryServiceFeign inventoryFeign;
@Transactional
public void createOrder(OrderDTO orderDTO) {
try {
// Step 1: Try 阶段
inventoryFeign.tryReserve(new InventoryTryDTO(orderDTO.getProductId(), orderDTO.getCount()));
// Step 2: 创建订单 (本地事务)
// saveOrder(orderDTO);
// Step 3: Confirm 阶段(通常由事务消息触发或协调器统一调度)
inventoryFeign.confirmReserve(new InventoryConfirmDTO(orderDTO.getOrderId()));
} catch (Exception e) {
// Step 4: Cancel 阶段
inventoryFeign.cancelReserve(new InventoryCancelDTO(orderDTO.getOrderId()));
throw e;
}
}
}
冗余库存总数处理
如果有一张表冗余了产品的库存总数,则需要额外增加一个库存冻结字段。

相似文章
文章作者 pengxiaochao
上次更新 2025-10-22
许可协议 不允许任何形式转载。