CAP 三选二公式误导性

理解 CAP

处理策略

CAP 和延迟的联系

理解 CAP

想象两个节点分处分区两侧

允许至少一个节点更新状态会导致数据不一致,即丧失 C 性质

如果为了保证数据一致性,将分区一侧的节点设置为不可用,又丧失了 A 性质

除非两个节点可以互相通信,才能既保证 C 又保证 A,又会导致丧失 P 性质

一般来说跨区域的系统,设计师无法舍弃 P 性质,只能在C和A做一个艰难选择

NoSQL 运动主题是创造各种A优先、C其次的方案;传统数据库坚守 ACID 特性,做的是相反的事情

再理解 CAP

但凡知道点分布式的人都对 CAP 理论耳熟能详,但真正要解释给别人时却总是难以自圆其说,像是一千个人眼中有一千个哈姆雷特

C 容易理解,所有节点上的数据都一样

P 是说一旦集群因为内部通信故障发生分裂,集群还能正常运转

关键是这个 A

咋一看 Availability 简直太好理解了,通常指系统能正常工作,系统架构所追求的 HA 即保证系统高可用,不宕机。企业级的 4 个 9,5 个 9 的,说的就是这个 A

但 CAP 理论里这个 A 却不是这个意思,《NoSQL Distilled》 里对这个问题专门做了澄清:

说白了就是 CAP 里的 A ,只要是活着的节点能返回响应,那么就认为它是 availability 的

用汽车来做个比喻:

汽车一切良好,故障灯一个都不亮,能开能刹,这是我们理解的传统 Available

车胎爆了,发动机坏了,或者是没油开不动了,这都已经是不可用

CAP 理论里,车不能开不要紧,只要是这车车门还能打开,那就是 Available 的

车胎破了能从胎压监测里看到,发动机坏了打火打不着,没油了油表灯会亮…… 这都是车返回的 response

只要是有 response,那么就是” 可用的

只满足 CA 的系统

P 定义: 集群因为内部通信故障发生分裂,集群还能正常运转。 舍弃 P 意味着一旦集群发生分裂,整个集群都将无法运转。这是符合 A 的,因为这是的节点是 fail 的,不需要给任何响应

单机服务器显然是 CA 的,只要结点活着,那自然是 C+A

而结点一旦挂了,整个集群也就没了,符合舍弃 P 的选择

只满足 CP 的系统

一旦集群内部因为内部通信故障发生分裂(假设分裂成两部分),为了满足 P,集群需要提供服务

而为了满足 C,只能保留其中一部分提供服务,让另一部分整体退役

只满足 AP 的系统

最容易理解,一旦集群内部因为内部通信故障发生分裂(假设分裂成两部分),为了满足 P,而又不需要满足 C,那么可以让分裂出来的两部分都提供服务,因为暂时数据不一致没关系

CAP 三选二公式误导性

CAP 理论断言任何基于网络的数据共享系统,最多只能满足数据一致性、可用性、分区容忍性三要素中的两个要素

三选二公式过分简单化各性质之间的相互关系,在分区存在的前提下呈现完美的数据一致性和可用性 这种很少见的情况是 CAP 理论不允许出现的

处理策略

分区很少发生,不存在分区的情况下没什么理由牺牲 C 或 A

C 与 A 之间的取舍可以在同一系统内以非常细小的粒度反复发生,每一次决策可能因为具体的操作,乃至因为牵涉到特定的数据或用户而有所不同

三种性质都可以在程度上衡量,不是非黑即白的有或无

可用性在 0% 到 100% 连续变化

一致性分很多级别

分区也可以细分为不同含义

  1. 探知分区发生
  2. 进入显式的分区模式以限制某些操作
  3. 启动恢复过程以恢复数据一致性并补偿分区期间发生的错误

CAP 和延迟的联系

CAP 理论的经典解释,是忽略网络延迟的,但实际延迟和分区紧密相关

CAP 从理论变为现实的场景发生在操作的间歇,系统需要在这段时间内做出关于分区的一个重要决定:

  • 取消操作因而降低系统的可用性,还是
  • 继续操作,以冒险损失系统一致性为代价

依靠多次尝试通信的方法来达到一致性,比如 Paxos 算法或者两阶段事务提交,仅仅是推迟了决策的时间

系统终究要做一个决定;无限期地尝试下去,本身就是选择一致性牺牲可用性的表现

实际效果而言,分区相当于对通信的时限要求

系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在 C 和 A 之间做出选择

这就从延迟的角度抓住了设计的核心问题:分区两侧是否在无通信的情况下继续其操作?

重要推论

第一,分区并不是全体节点的一致见解,有些节点检测到了分区,有些可能没有

第二,检测到分区的节点即进入分区模式——这是优化 C 和 A 的核心环节

这个观察角度意味着设计师可以根据期望中的响应时间,有意识地设置时限;时限设得越短,系统进入分区模式越频繁,其中有些时候并不一定真的发生了分区的情况,可能只是网络变慢而已

系统进入到分区模式,有两种可行的策略

其一是限制部分操作,削弱可用性

其二是额外记录一些有利于后面分区恢复的操作信息。系统可通过持续尝试恢复通信来察觉分区何时结束