一个分布式系统最多只能同时满足 一致性(Consistency) 、 可用性(Availability) 和 分区容错性(Partition tolerance) 这三项中的两项。
2000 年 7 月,加州大学伯克利分校的 Eric Brewer 教授在 ACM PODC 会议上提出 CAP 猜想。2 年后,麻省理工学院 Seth Gilbert 和 Nancy Lynch 从理论上证明了 CAP。之后,CAP 理论正式成为分布式计算领域的公认定理。
CAP 的定义
Consistency 一致性
一致性指all nodes see the same data at the same time
,即所有节点在同一时间的数据完全一致。
一致性是因为多个数据拷贝下并发读写才有的问题,因此理解时一定要注意结合考虑多个数据拷贝下并发读写的场景。对于一致性,可以分为从客户端和服务端两个不同的视角。
客户端
从客户端来看,一致性主要指的是多并发访问时更新过的数据如何获取的问题。服务端
从服务端来看,则是更新如何分布到整个系统,以保证数据最终一致。
从客户端角度,多进程并发访问时,更新过的数据在不同进程如何获取的不同策略,决定了不同的一致性。对于一致性,可以分为强/弱/最终一致性三类。
强一致性
对于关系型数据库,要求更新过的数据能被后续的访问都能看到,这是强一致性。弱一致性
如果能容忍后续的部分或者全部访问不到,则是弱一致性。最终一致性
如果经过一段时间后要求能访问到更新后的数据,则是最终一致性。
Availability 可用性
可用性指Reads and writes always succeed
,即服务一直可用,而且是正常响应时间。
对于一个可用性的分布式系统,每一个非故障的节点必须对每一个请求作出响应。所以,一般我们在衡量一个系统的可用性的时候,都是通过停机时间来计算的。
通常我们描述一个系统的可用性时,我们说淘宝的系统可用性可以达到 5 个 9,意思就是说他的可用水平是 99.999%,即全年停机时间不超过 (1-0.99999)*365*24*60 = 5.256 min
,这是一个极高的要求。
Partition Tolerance 分区容错性
分区容错性指the system continues to operate despite arbitrary message loss or failure of part of the system
,即分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务。在实际应用中指的是集群架构和数据支持动态横向扩展。所谓动态,就是不停机。
CAP 的权衡
CA without P
如果不要求 P(分区),则 C(一致性)和 A(可用性)是可以保证的。但其实分区不是你想不想的问题,而是始终会存在,因此 CA 的系统更多的是允许分区后各子系统依然保持 CA。
但放弃 P 的同时也就意味着放弃了系统的扩展性,也就是分布式节点受限,没办法部署子节点,这是违背分布式系统设计的初衷的。
CP without A
如果不要求 A(可用),相当于每个请求都需要在 Server 之间强一致,而 P(分区)会导致同步时间无限延长,如此 CP 也是可以保证的。很多传统的数据库分布式事务都属于这种模式。
对于涉及到钱财这样不能有一丝让步的场景,C 必须保证。网络发生故障宁可停止服务,这是保证 CA,舍弃 P。貌似这几年国内银行业发生了不下 10 起事故,但影响面不大,报道也不多,广大群众知道的少。还有一种是保证 CP,舍弃 A。例如网络故障事只读不写。
AP wihtout C
要高可用并允许分区,则需放弃一致性。一旦分区发生,节点之间可能会失去联系,为了高可用,每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。现在众多的 NoSQL 都属于此类。
对于多数大型互联网应用的场景,主机众多、部署分散,而且现在的集群规模越来越大,所以节点故障、网络故障是常态,而且要保证服务可用性达到 N 个 9,即保证 P 和 A,舍弃 C(退而求其次保证最终一致性)。虽然某些地方会影响客户体验,但没达到造成用户流程的严重程度。