4. 一致性模型选型
一致性模型不是“越强越好”的单选题,而是正确性约束、延迟预算、可用性目标与实现成本之间的联合取舍。选型的核心动作是:先明确业务对“读到的值必须满足什么关系”的最低要求,再选择刚好覆盖该要求的最弱模型,从而把性能和可用性留出余量。下面按约束强度从强到弱梳理五种模型的语义边界,并给出可落地的判断方法。
五种模型的语义边界
强一致性(Strict Consistency)要求任何读操作都能立即返回最近一次写的结果,隐含“绝对全局时钟”假设。在分布式系统中它几乎无法工程化实现,通常只作为理论基准,实际系统用线性一致性作为可实现的“强”替代。
线性一致性(Linearizability)是可实现的最强模型:所有操作看起来在某个全局时间点原子生效,且该时间点落在操作的调用与返回之间。它保证读到的值不会“倒退”,也不会读到已被覆盖的旧值。典型实现依赖共识协议(Raft、Paxos、ZAB),写需多数派确认,读需经 Leader 或 ReadIndex 校验。代价是写延迟受多数派 RTT 约束,分区时少数派不可用。
顺序一致性(Sequential Consistency)只要求所有节点看到相同的操作顺序,但不要求该顺序与真实时间一致。它比线性一致性弱:允许读到稍旧的值,只要全局顺序统一。实现上可用单点定序或逻辑时钟排序,延迟低于线性一致性,但仍需全局协调,扩展性受限。
因果一致性(Causal Consistency)只保证有因果关系的操作按序可见:若写 W1 因果先于 W2,则任何节点不会先看到 W2 再看到 W1;无因果关系的并发写可任意排序。它用向量时钟或版本向量追踪依赖,无需全局协调,分区两侧可独立读写,恢复后合并。适合社交动态、评论回复、协同编辑等“因果比实时更重要”的场景。
最终一致性(Eventual Consistency)只承诺停止写入后,经过有限时间所有副本收敛到相同值,不约束中间过程。它可用异步复制、反熵、CRDT 实现,延迟最低、可用性最高,但读可能返回旧值、冲突需业务层解决。
生产权衡的三个关键维度
延迟与吞吐。线性一致性写需等待多数派确认,跨机房部署时写延迟通常为同机房 RTT 的 2~3 倍;因果一致性只需本地写入并异步传播依赖,延迟接近单机。若业务 P99 延迟预算为 50ms 且跨三机房,线性一致性往往难以达标,此时应重新审视是否真的需要“读最新”。
可用性与分区行为。根据 CAP,线性一致性与顺序一致性在分区时必须在一致性和可用性间二选一;因果一致性与最终一致性允许分区两侧继续服务,恢复后合并。生产上常见的折中是:核心交易走线性一致性,商品详情、评论、推荐走因果或最终一致性,通过业务分层把强约束限制在最小范围。
冲突解决成本。最终一致性把冲突推给业务:需要定义 Last-Write-Wins、版本合并或 CRDT 语义。若业务无法给出确定的合并规则,最终一致性会变成“数据永久不一致”。因果一致性通过版本向量保留了因果依赖,冲突范围更小,但需要存储和传播向量时钟,元数据开销随节点数增长。
可执行的选型检查表
下表可作为评审时的填写模板,逐项确认后再定模型,避免“默认上强一致”或“默认上最终一致”的惯性决策。
| 检查项 | 判断问题 | 若“是”倾向 | 若“否”倾向 |
|---|---|---|---|
| 读最新 | 读操作是否必须返回最近一次写? | 线性一致性 | 继续下一项 |
| 全局顺序 | 所有节点是否必须看到相同操作顺序? | 顺序一致性 | 继续下一项 |
| 因果依赖 | 是否存在“先评论后回复”等因果链? | 因果一致性 | 最终一致性 |
| 冲突规则 | 并发写冲突是否有确定的合并规则? | 可放宽到最终一致性 | 需因果或更强模型 |
| 延迟预算 | P99 延迟是否允许多数派 RTT? | 可考虑线性一致性 | 降级到因果/最终 |
| 分区容忍 | 分区时是否必须双侧可写? | 因果或最终一致性 | 可接受少数派不可用 |
落地时建议按数据域拆分:账户余额、库存扣减、订单状态机使用线性一致性;配置中心、分布式锁使用顺序一致性;评论、点赞、动态流使用因果一致性;商品画像、推荐特征、日志聚合使用最终一致性。每个数据域在接口层显式声明其一致性等级,并在监控中观察读旧值比例、冲突率和收敛延迟,用真实数据反向验证选型是否成立。