分布式事务的挑战
在前后端分离架构中,服务模块化导致跨服务调用频繁,传统单体事务模型无法满足需求。分布式事务需要解决网络延迟、服务宕机、数据不一致等问题,最终一致性成为核心目标。
两阶段提交(2PC)方案
两阶段提交通过协调者(Coordinator)和参与者(Participant)的角色划分实现事务控制。第一阶段协调者询问所有参与者是否就绪,第二阶段根据反馈提交或回滚。该方案强一致但存在同步阻塞问题,适用于银行转账等高一致性场景。
// 伪代码示例
public class TwoPC {
public boolean prepare() { /* 资源锁定逻辑 */ }
public void commit() { /* 提交逻辑 */ }
public void rollback() { /* 回滚逻辑 */ }
}
补偿事务(TCC)模式
Try-Confirm-Cancel模式将事务拆分为三个阶段:Try阶段预留资源,Confirm阶段确认操作,Cancel阶段回滚补偿。需业务方实现补偿接口,适用于电商订单等需要明确补偿逻辑的场景。
def tcc_order():
try:
freeze_inventory() # Try
confirm_payment() # Confirm
except Exception:
unfreeze_inventory() # Cancel
消息队列异步通知
通过消息队列实现事务消息的可靠投递,结合本地事务表确保消息必达。RocketMQ的事务消息机制是典型实现,生产者先发送半消息,本地事务成功后提交二次确认。
-- 本地事务表设计示例
CREATE TABLE transaction_log (
id VARCHAR(36) PRIMARY KEY,
business_type VARCHAR(50),
status TINYINT,
create_time DATETIME
);
本地消息表方案
业务与消息耦合的方案,在同一个数据库事务中完成业务操作和消息记录。通过定时任务扫描消息表进行重试,保证数据最终一致。需注意幂等设计和去重机制。
最大努力通知
适用于对一致性要求不高的场景,通过定期重试+报警机制结合。典型应用如支付结果通知,设置最大重试次数和超时阈值,配合人工稽核流程。
版本号控制
采用乐观锁机制,通过数据版本号或时间戳控制并发修改。前端提交请求时携带版本号,服务端校验版本一致性,冲突时要求客户端重新获取数据。
// 请求体示例
{
"id": 123,
"version": 3,
"data": {"price": 299}
}
前端补偿设计
前端需实现操作状态持久化、重试机制和冲突提示。采用Loading状态禁止重复提交,异常时保留表单数据,通过WebSocket或轮询获取最终状态。
// 前端提交重试逻辑
const retrySubmit = async (payload, maxRetry = 3) => {
let attempt = 0;
while (attempt < maxRetry) {
try {
return await api.submit(payload);
} catch (error) {
attempt++;
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
}
}
throw new Error('Max retry exceeded');
};
监控与告警体系
建立分布式事务监控看板,跟踪关键指标:事务成功率、平均处理时间、积压消息数等。设置自动告警规则,对长时间未完成的事务触发预警,便于及时人工干预。