php 实现tcc

TCC 模式简介
TCC(Try-Confirm-Cancel)是一种分布式事务解决方案,适用于需要高一致性的场景。其核心思想是将事务拆分为三个阶段:
- Try:预留资源,完成业务检查(如冻结账户余额)。
- Confirm:确认执行业务,提交预留资源(如扣减冻结金额)。
- Cancel:取消业务,释放预留资源(如解冻金额)。
PHP 实现 TCC 的关键步骤
数据库设计
创建事务记录表,存储事务状态和业务数据:
CREATE TABLE tcc_transaction (
id VARCHAR(36) PRIMARY KEY,
status ENUM('trying', 'confirmed', 'cancelled') NOT NULL,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
Try 阶段实现
- 生成全局事务 ID 并记录状态为
trying。 - 执行业务检查(如库存检查),预留资源(如冻结库存)。
function tryOperation($orderId, $amount) { $transactionId = uniqid(); // 记录事务状态 DB::insert('INSERT INTO tcc_transaction (id, status) VALUES (?, ?)', [$transactionId, 'trying']); // 业务操作:冻结资源 DB::update('UPDATE account SET frozen = frozen + ? WHERE user_id = ?', [$amount, $userId]); return $transactionId; }
Confirm 阶段实现
- 检查事务状态是否为
trying。 - 提交资源(如扣减冻结金额)。
- 更新事务状态为
confirmed。function confirmOperation($transactionId) { $status = DB::select('SELECT status FROM tcc_transaction WHERE id = ?', [$transactionId]); if ($status !== 'trying') { throw new Exception("Invalid transaction state"); } // 提交业务操作 DB::update('UPDATE account SET balance = balance - frozen, frozen = 0 WHERE user_id = ?', [$userId]); DB::update('UPDATE tcc_transaction SET status = ? WHERE id = ?', ['confirmed', $transactionId]); }
Cancel 阶段实现
- 检查事务状态是否为
trying。 - 释放预留资源(如解冻金额)。
- 更新事务状态为
cancelled。function cancelOperation($transactionId) { $status = DB::select('SELECT status FROM tcc_transaction WHERE id = ?', [$transactionId]); if ($status !== 'trying') { throw new Exception("Invalid transaction state"); } // 回滚业务操作 DB::update('UPDATE account SET frozen = 0 WHERE user_id = ?', [$userId]); DB::update('UPDATE tcc_transaction SET status = ? WHERE id = ?', ['cancelled', $transactionId]); }
注意事项
- 幂等性:确保 Confirm/Cancel 操作可重复执行而不产生副作用。
- 重试机制:通过定时任务补偿未完成的事务(如长时间处于
trying状态的事务)。 - 隔离性:业务表需设计冻结字段(如
frozen),避免脏读或并发冲突。
通过以上步骤,PHP 可实现基本的 TCC 事务模式,适用于订单、支付等分布式场景。







