1) 【一句话结论】在微服务中,订单服务调用库存和支付服务时,分布式事务需通过Saga模式(分步执行+补偿)或最终一致性(异步更新+状态机)实现,两阶段提交因阻塞和单点故障风险高,不推荐用于微服务。
2) 【原理/概念讲解】
分布式事务的核心是跨服务数据一致性。
- 两阶段提交(2PC):协调者(订单服务)发起,第一阶段询问各参与者(库存、支付)是否准备提交,第二阶段协调者决定提交或回滚。类比:银行转账,总行(协调者)通知各分行(参与者)是否同意转账,再统一执行。但问题:协调者故障导致所有参与者阻塞,参与者故障导致数据不一致。
- Saga模式:将事务拆分为多个本地事务,按顺序执行,每个步骤的本地事务提交后,通过消息队列通知下一个步骤,若某步骤失败,通过补偿事务回滚。类比:餐厅点餐,点餐(订单)→下单(库存扣减)→支付(支付扣减),若支付失败,库存需补偿(加回库存)。
- 最终一致性:各服务异步更新状态,通过事件总线或消息队列通知,最终通过状态机(如订单状态机)确保一致性,适用于对实时性要求不高的场景,如电商订单状态(待支付→支付中→已支付)。
3) 【对比与适用场景】
| 方案 | 定义 | 特性 | 使用场景 | 注意点 |
|---|
| 两阶段提交(2PC) | 集中式协调,协调者控制参与者提交/回滚 | 集中式控制,阻塞式,强一致性 | 需强一致性,服务数量少,网络稳定 | 协调者故障导致阻塞,参与者故障导致数据不一致 |
| Saga模式 | 分步本地事务,失败时补偿 | 分布式,异步,最终一致性 | 业务流程长,步骤多,部分步骤失败需补偿 | 补偿逻辑复杂,可能产生循环补偿 |
| 最终一致性 | 各服务异步更新,通过状态机最终一致 | 异步,松耦合,弱一致性 | 对实时性要求低,如订单状态、用户数据 | 需状态机保证最终一致,可能存在短暂不一致 |
4) 【示例】(Saga模式)
订单服务调用库存服务扣减库存,成功后调用支付服务扣款,支付成功后订单状态更新为“已完成”。若支付失败,支付服务发送补偿消息给库存服务,库存服务加回库存,订单状态更新为“库存已恢复”。
伪代码:
- 订单服务:
- 创建订单(本地事务,状态=待支付)
- 调用库存服务:扣减库存(库存服务本地事务,库存-1,状态=扣减中)
- 调用支付服务:扣款(支付服务本地事务,金额-1,状态=扣款中)
- 若支付成功:
- 更新订单状态为“已完成”
- 调用库存服务确认扣减(库存服务本地事务,库存+1,状态=恢复中)
- 若支付失败:
- 调用库存服务发送补偿消息(库存服务监听消息,加回库存,库存+1,状态=恢复完成)
- 更新订单状态为“库存已恢复”
5) 【面试口播版答案】
“在微服务中,订单服务调用库存和支付服务时,分布式事务常用Saga模式或最终一致性。比如,订单服务先扣减库存,再调用支付服务,若支付失败,库存会通过补偿事务加回。两阶段提交因阻塞和故障风险高,不推荐。具体来说,Saga将事务拆分为多个本地步骤,每个步骤成功后通知下一个,失败则补偿,保证最终一致性。对于订单场景,Saga能处理业务流程的失败补偿,而最终一致性适用于对实时性要求不高的状态更新。”
6) 【追问清单】
- 问:2PC为什么在微服务中不推荐?
回答要点:2PC阻塞式,协调者故障导致所有参与者阻塞,参与者故障导致数据不一致,不适合微服务高可用。
- 问:Saga的补偿逻辑如何设计?
回答要点:补偿事务需与原事务相反,比如扣减库存的补偿是加回库存,需考虑业务场景,避免循环补偿。
- 问:最终一致性中,订单状态如何保证一致?
回答要点:通过状态机(如订单状态机,定义状态转换规则),各服务异步更新状态,状态机最终确保状态正确。
- 问:Saga和最终一致性的区别?
回答要点:Saga是强一致性(分步执行,失败补偿),最终一致性是弱一致性(异步更新,最终通过状态机),Saga适用于业务流程长且需补偿的场景,最终一致性适用于对实时性要求低的状态更新。
- 问:如果库存服务调用支付服务失败,如何处理?
回答要点:库存服务失败后,通过消息队列发送补偿消息给支付服务,支付服务加回金额,订单状态更新为“库存已恢复”。
7) 【常见坑/雷区】
- 忽略2PC的阻塞问题,认为其适合微服务。实际微服务需高可用,2PC协调者故障会导致服务阻塞。
- Saga补偿逻辑设计不当,导致循环补偿。比如支付失败后,库存补偿,但库存补偿后支付服务又失败,导致库存再次补偿,循环。
- 最终一致性中,状态机设计错误,导致数据不一致。比如订单状态机转换规则错误,导致状态错误。
- 忽略Saga的异步消息延迟问题,导致补偿失败。比如消息队列延迟,导致库存补偿不及时,订单状态错误。
- 将Saga和最终一致性混淆,认为最终一致性就是Saga。实际Saga是分步执行+补偿,最终一致性是异步更新+状态机。