互联网产品服务端多采用微服务分布式架构来解决因系统规模增长而带来的开发效率、技术多样性和弹性伸缩问题(延伸阅读:《分布式系统缘起及理论》)。与此同时,随着业务单元被拆分到多个微服务,业务逻辑也随之被拆分,比如电商下单操作,必须同时在订单服务中创建订单,商品服务中扣减库存。如何保证这些分布式操作的一致性是分布式系统的核心难题。本文基于多年实践经验,总结了常用的分布式操作一致性方案。
一、基础理论
CAP理论
CAP理论是分布式系统设计的基础,它指出在一个分布式系统中,一致性(Consistency) 、可用性(Availability) 和分区容错性(Partition Tolerance) 三者不可兼得,最多只能同时实现两项。

分布式操作的努力方向:保P,AC间取舍(酸碱acid-base不可兼得)
酸碱理论
CAP理论指出分布式操作只能选择 CP 或 AP:
- CP保证ACID特性(酸性):强一致性,阻塞可用
- AP保证BASE特性(碱性):弱一致性,高可用

二、一致性方案
2.1 AC:单库(去P)方案
|-------------------------------------------------------------------------------------------------------------------------------|
| 如果技术方案可以让操作集中到 MySQL 单库上,便可低成本实现AC保证。 【注意】 * 要求主库读写 * NoSQL库批量操作key不保证ACID 【建议】 * 业务场景设计MySQL数据表时,尤其是多库多表时,优先考虑是否能将多个操作集中到单库。 |
2.2 CP方案
选择CP意味着存在不A时刻,一般互联网产品线上业务较少需要CP保证,本文暂不讨论。
2.3 AP+最终一致
方案要点:
-
需要一个旁观者角色
-
旁观者在操作异常时保证最终一致
-
保证操作的幂等性
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 方案一:TCC(旁观者角色:事务管理器) |
| TCC三个阶段的核心操作: * Try阶段:尝试执行业务检查,预留必要的业务资源,保障一致性和准隔离性。 * Confirm阶段:当所有分支的Try都成功时,TM会发出Confirm指令。Confirm阶段会真正执行业务操作,通常不再进行业务检查,直接使用Try阶段预留的资源。此操作需保证幂等性。 * Cancel阶段:如果任何分支的Try操作失败,TM会发起Cancel指令。Cancel阶段会释放Try阶段预留的业务资源(如解冻资金)。此操作同样需保证幂等性。 TCC时序图(以下单扣库存为例): 【优点】 * 高性能,低锁竞争。仅在Confirm阶段加全局锁,这个阶段非常快,因为Try阶段已完成前置校验和资源准备。 * 较强的一致性。正常情况Confirm成功能提供强一致性。异常情况Cancel保证最终一致性。 【缺点】 * 开发复杂度高,业务侵入性强。需要所有业务操作都提供三阶段实现。 * 需要考虑多种异常:空回滚,防悬挂,幂等性控制等。 【建议】 一致性要求较高(毫秒级)的场景使用,如涉及用户重要资产(积分,抵扣金等)变更的操作。 |
| 方案二:事务消息(旁观者角色:消息平台) |
| 事务消息方案分为两个阶段处理: * 第一阶段:发送半消息后,进行本地事务处理 * 第二阶段:事务消息消费阶段,保证所有操作最终都做完或都回滚完 由于第一阶段先发送了半消息,消息平台通过事务回查能保证消息一定能发送/回滚,即一定能进入第二阶段。 【优点】 * 业务侵入低,实现成本低 * 不要求每个操作都提供TCC那样的接口 * 不要求每个操作都可回滚 * 性能好,第二阶段是异步处理 【缺点】 * 相比TCC所有接口都是同步调用,异步消息处理最终一致性的时延更长 【建议】 * 接受秒级最终一致性的场景,优先采用此方案 * 最佳实践: * 第一阶段: * 本地事务做所有分布式操作 * 正常情况下本地事务能全部完成(毫秒级一致),此时回滚掉消息免去第二阶段 * 异常情况才Commit消息进入第二阶段 * 第二阶段: * 最终做完:对第一阶段没有完成的操作保证全部完成(重试+幂等) * 或 * 最终回滚:对第一阶段已完成的操作保证全部回滚(重试+幂等) |
| 方案三:redoLog方案(旁观者角色:消息平台) |
| 此方案借鉴MySQL持久化redoLog思想: * 分布式操作前先记录下要做的操作 * 旁观者检查redoLog保证操作最终做完(定时任务或延迟消息等) 【适用场景】 * 一次要处理较多分布式操作的场景(如批量给多个用户发券) * 接受分钟级最终一致性延迟 * redoLog增长速度 小于 旁观者处理速度 |
| 方案四:最大努力通知+对账方案(旁观者角色:对账任务) |
| 此方案在分布式操作过程中只做最大努力尝试,不保证一定成功,甚至不关心成功与否。通过对账保证最终一致。 【适用场景】 * 接受小时级甚至天级最终一致性延迟 * 最大努力操作是弱依赖,不阻塞主操作的业务逻辑 * 适合B端数据同步操作 |
| 方案五: 用户重复操作方案(旁观者角色:用户) |
| 此方案依赖产品交互设计,在分布式操作未全部成功时,引导用户重复操作,实现最终一致。 【适用场景】 * 分布式操作重复执行后能保证最终全部成功(不能回滚) * 不一致状态不影响用户体验和业务逻辑 * 接受可能永久不一致(用户可能不再重试) * 适合用户操作推动状态转移场景 |
2.4 AP+接受小概率不一致
++接受小概率不一致的操作:++
- 统计类操作:在不影响统计数量级差异的前提下,可接受小概率不一致
- 采样类操作:如活动氛围采样
- 可降级操作:如发券后,生产消息通知用户
- 可恢复操作:如缓存数据丢失,可从DB恢复,更新缓存操作就是一种可恢复操作
务必评估不一致对业务的影响,确保不一致造成的风险可控。
三、总结
CAP理论指出一致性,可用性,分区容错性三者不可兼得,只能保其二:
-
AC:去P方案,技术方案设计时优先考虑能否将操作集中到单库上。
-
CP:牺牲可用性,互联网线上业务较少需要CP保证。
-
AP+最终一致性:
-
TCC方案:毫秒级最终一致
-
事务消息方案:秒级最终一致
-
redoLog方案:分钟级延迟,适合一次处理较多分布式操作的场景
-
最大努力通知+对账方案:小时级或天级延迟,适合B端数据同步场景
-
用户重复操作方案:适合用户操作推动状态转移场景
-
-
AP+接受小概率不一致:
- 统计类操作:在不影响统计数量级差异的前提下,可接受小概率不一致
- 采样类操作:如活动氛围采样
- 可降级操作:如发券后,生产消息通知用户
- 可恢复操作:如缓存数据丢失,可从DB恢复,更新缓存操作就是一种可恢复操作
