许吉友 - 运维

CAP 理论

一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项

Consistency 一致性

对于关系型数据库,要求更新过的数据能被后续的访问都能看到,这是强一致性。

如果能容忍后续的部分或者全部访问不到,则是弱一致性。

如果经过一段时间后要求能访问到更新后的数据,则是最终一致性。

Availability 可用性

每个请求都会收到一个(非错误)响应,但不能保证它包含最新的写入

好的可用性主要是指系统能够很好的为用户服务,不出现用户操作失败或者访问超时等用户体验不好的情况。可用性通常情况下可用性和分布式数据冗余,负载均衡等有着很大的关联。

Partition Tolerance 分区容错性

尽管节点之间的网络丢弃(或延迟)了任意数量的消息,但系统仍继续运行。

一个分布式系统里面,节点组成的网络本来应该是连通的。然而可能因为一些故障,使得有些节点之间不连通了,整个网络就分成了几块区域。数据就散布在了这些不连通的区域中。这就叫分区。

分类

CA without P:如果不要求P(不允许分区),则C(强一致性)和A(可用性)是可以保证的。但其实分区不是你想不想的问题,而是始终会存在,因此CA的系统更多的是允许分区后各子系统依然保持CA。

CP without A:如果不要求A(可用),相当于每个请求都需要在Server之间强一致,而P(分区)会导致同步时间无限延长,如此CP也是可以保证的。很多传统的数据库分布式事务都属于这种模式。

AP wihtout C:要高可用并允许分区,则需放弃一致性。一旦分区发生,节点之间可能会失去联系,为了高可用,每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。现在众多的NoSQL都属于此类。

但也不是单纯的只取其二,很多系统只是弱化某些特性来支持其他两者。

CAP理论中的P到底是个什么意思?

一个分布式系统里面,节点组成的网络本来应该是连通的。然而可能因为一些故障,使得有些节点之间不连通了,整个网络就分成了几块区域。数据就散布在了这些不连通的区域中。这就叫分区。

当你一个数据项只在一个节点中保存,那么分区出现后,和这个节点不连通的部分就访问不到这个数据了。这时分区就是无法容忍的。

提高分区容忍性的办法就是一个数据项复制到多个节点上,那么出现分区之后,这一数据项就可能分布到各个区里。容忍性就提高了。

然而,要把数据复制到多个节点,就会带来一致性的问题,就是多个节点上面的数据可能是不一致的。要保证一致,每次写操作就都要等待全部节点写成功,而这等待又会带来可用性的问题。

总的来说就是,数据存在的节点越多,分区容忍性越高,但要复制更新的数据就越多,一致性就越难保证。为了保证一致性,更新所有节点数据所需要的时间就越长,可用性就会降低。

作者:邬江 链接:https://www.zhihu.com/question/54105974/answer/139037688 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

我的理解

CAP是一套分布式理论,C 表示一致性,A 表示可用性,P 表示分区容错性。

理论认为只能满足其中两个,另外一个肯定不能满足,现代工程上都会满足其中两项,而弱化其中一项。

三个不能同时满足的原因很简单,就是网络传输数据需要时间,而且网络可能会断,服务可能会挂。

首先 P 表示分区容错性,可以理解为数据有多少副本,副本越多,数据肯定越安全。如果不想要分区容错性,那数据只有一份,它就成了光杆司令了,肯定完美解决一致性和可用性的问题。现代分布式集群为了保证数据安全,都会保存多个副本,或者利用纠删码,比如 HDFS、ES、Kafka、Etcd 、Ceph、MinIO 等。

其次是 C 一致性,它强调所有人手里都有一份数据。现代分布式集群大多数都不会实现强一致性,一般都会实现最终一致性,为了获得更好的性能,通常只要多于一半节点确认更新了数据就会表明自己更新完毕了。

最后 A 可用性,现在都在强调高可用,毋庸置疑,肯定要保证可用性。

综上,对于大多数开源组件的分布式集群来说,P 保证了数据安全、A 保证了用户体验,所以 C 就是那个为了性能被牺牲的了。但是对于涉及到钱财的领域(事务)来说,通常会保证强一致性,而牺牲可用性,毕竟把钱弄丢了不是小事情。

所以,P 分区容错性在生产环境中一定会被满足,但是在数据不重要的场景中(比如做 Demo),就不必非要满足了。