CAP 讨论的是分区发生时一致性与可用性的取舍

澄清 CAP 中一致性、可用性和网络分区的定义,说明分区期间请求处理为何必须围绕业务不变量选择。

CAP 讨论的是分区发生时一致性与可用性的取舍

CAP 常被缩写成“分布式系统只能三选二”,这句话省略了最重要的条件。形式化结论讨论的是异步网络发生通信分区时,系统无法同时保证特定的一致性和每个请求都得到成功响应的可用性。网络正常时,系统仍可以同时提供低延迟和强一致行为。

架构决策不能只给数据库贴上 CP 或 AP 标签。需要说明分区怎样被检测、哪些操作可以继续、哪些业务不变量必须保护,以及恢复后怎样合并状态。

分区容忍不是可自由关闭的选项

多个节点通过网络通信时,消息可能延迟、丢失或长时间无法到达。系统无法可靠区分对方已经崩溃,还是网络只是很慢。只要服务跨故障域部署,设计就必须考虑这种不确定性。

选择“不容忍分区”通常意味着分区时整体停止或退化为单一可通信区域,而不是让网络分区消失。对于单机系统,CAP 不是主要分析工具;一旦复制跨节点,分区行为就需要明确。

超时只能让调用者停止等待,不能证明远端操作没有发生。客户端重试可能在另一侧形成重复写入,因此幂等和请求标识仍是必要机制。

一致性在 CAP 中有严格含义

CAP 讨论的一致性接近单对象原子一致性:每次操作看起来在某个瞬间发生,所有客户端观察到与单副本顺序一致的结果。它不同于数据库约束、事务隔离级别或副本最终收敛这些其他含义。

如果一个分区中的客户端完成写入,另一个隔离分区继续返回旧值,就无法同时维持这种单一实时顺序。系统可以阻止一侧读写,或允许陈旧和冲突,从而作出取舍。

业务可能不需要所有字段同样强。余额扣减需要保护不超支,商品描述可以稍后同步。把状态按不变量分类,比对整个系统贴一个一致性标签更有用。

可用性也不是通常所说的百分比

形式化可用性要求每个发送到未故障节点的请求最终得到非错误响应,不允许因为无法联系另一分区而拒绝。它不等于年度 99.9% SLO,也没有规定响应必须在某个毫秒内完成。

现实系统可以在分区时对读请求保持可用,对高风险写入返回明确错误;也可以只允许拥有租约或多数派的一侧继续。这样的局部策略无法用一个 A 或 C 字母完整描述。

返回成功但结果不满足业务语义,不应被当作可用。若购物车接受更新却永久丢失,形式上的响应并没有实现用户目标。可用性设计仍需结合持久性和恢复。

分区期间选择围绕具体操作展开

强一致路径通常要求写入获得多数或领导者确认。少数分区会拒绝操作,保护单一顺序。好处是恢复后不需合并两个已承诺事实,代价是部分用户在分区期间无法完成请求。

高可用路径允许各侧独立接受更新,之后通过版本、向量时钟、集合合并或业务规则解决冲突。它适合可交换、可合并或可补偿的数据,不适合所有金融和库存不变量。

同一服务可以混合两类路径。例如创建草稿可离线,发布唯一 slug 必须获得全局协调。接口应把临时接受、最终确认和冲突状态明确返回给客户端。

Dynamo 展示了可用性取向的具体代价

Dynamo 设计面向持续可写,使用一致性哈希分布数据,通过可配置读写仲裁、提示移交和读修复处理节点不可达。版本之间的并发关系由向量时钟辅助判断,无法自动合并时把冲突交给应用。

这些机制不是免费获得的“最终一致”。客户端或业务必须有合并语义,临时副本要在恢复后归还数据,删除还需墓碑避免旧值复活。后台修复和反熵也消耗容量。

一个系统采用类似术语,不代表获得同样保证。仲裁是否严格、失败节点怎样替代、读修复何时发生,都依赖具体实现和配置。

网络恢复不代表状态自动正确

分区结束后,两侧可能有并发版本、积压日志和过期租约。恢复流程需要识别冲突、重放顺序、重复副作用和客户端已见结果。简单以最后写入时间覆盖,会受时钟偏差影响并丢失合法更新。

若分区时停止少数派写入,恢复仍需追赶日志和验证数据完整性。节点在同步完成前不应参与读取,否则会把陈旧状态重新暴露。

审计记录应保留分区开始、路由变化、拒绝操作和恢复决定。只有最终值而没有冲突过程,很难解释用户为何看到状态回退。

测试要主动制造通信故障

正常压测无法验证分区语义。应阻断节点间特定方向的流量,模拟高延迟、丢包、DNS 分裂和不对称通信,并观察客户端超时、领导者、写入确认与恢复。

测试断言要基于不变量:是否出现重复扣款、两个领导者是否都承诺冲突操作、已确认写入是否丢失。只看集群最终变绿会漏掉用户已遭遇的错误。

告警应区分节点故障、复制滞后和仲裁丢失。自动故障转移也要有防抖和权限,防止控制面在不稳定网络中反复切换。

CAP 的价值是揭示分区下无法同时满足的严格目标,而不是提供数据库选型口诀。把一致性与可用性定义还原到具体请求和业务不变量,才能设计清楚的拒绝、降级与恢复行为。

资料依据