php实现tcc
PHP实现TCC(Try-Confirm-Cancel)模式
TCC模式是一种分布式事务解决方案,通过业务逻辑拆分补偿机制替代传统2PC(两阶段提交)。以下是PHP实现的要点:
核心流程设计
Try阶段
预留资源,冻结状态。例如订单系统预扣库存,账户系统冻结金额。需记录操作日志,支持幂等性。
class OrderService {
public function tryCreateOrder($orderData) {
// 1. 检查库存
// 2. 生成预订单(状态为TRYING)
// 3. 记录事务日志到独立表
return ['status' => 'TRYING', 'tx_id' => uniqid()];
}
}
Confirm阶段
确认操作,更新为最终状态。需保证幂等,避免重复确认。
class PaymentService {
public function confirmPayment($txId) {
// 1. 检查事务日志是否已存在CONFIRMED记录
// 2. 更新账户余额(解冻金额)
// 3. 更新事务状态
return ['status' => 'CONFIRMED'];
}
}
Cancel阶段
回滚Try阶段操作。需处理悬挂问题(Try未执行但收到Cancel)。
class InventoryService {
public function cancelReservation($txId) {
// 1. 检查是否已执行过Try
// 2. 恢复库存
// 3. 标记事务为CANCELLED
return ['status' => 'CANCELLED'];
}
}
事务协调器实现
定时任务补偿
通过后台任务扫描超时事务,触发补偿:
class TccCoordinator {
public function checkTimeoutTransactions() {
$expiredTx = TransactionLog::where('status', 'TRYING')
->where('created_at', '<', now()->subMinutes(30))
->get();
foreach ($expiredTx as $tx) {
$this->triggerCancel($tx->service, $tx->tx_id);
}
}
}
技术要点
幂等性控制
所有操作需通过事务ID保证幂等:
DB::transaction(function() use ($txId) {
if (TransactionLog::where('tx_id', $txId)->exists()) {
return;
}
// 执行业务操作
});
悬挂问题解决
Cancel前检查Try是否执行:
if (!TransactionLog::where('tx_id', $txId)->where('phase', 'TRY')->exists()) {
// 记录未完成的Cancel请求
PendingCancel::create(['tx_id' => $txId]);
}
框架集成建议
- 使用Laravel/ThinkPHP等框架的事件系统触发Confirm/Cancel
- 通过中间件实现分布式事务上下文传递
- 结合Redis实现分布式锁控制并发
注意事项
- 各服务需暴露TCC接口(Try/Confirm/Cancel)
- 事务日志表需包含:事务ID、业务类型、当前阶段、创建时间
- 建议采用最终一致性,而非强一致性
完整实现需结合具体业务场景调整补偿策略和超时时间。可通过Swoole协程提升高并发下的性能表现。







