CAP 定义

在一个分布式系统中,当涉及读写操作时,只能保证一致性(Consistency)、可用性(Availability )、分区容忍性(Partition tolerance)三者中的两个,另一个必须有所牺牲(不是完全放弃)。

Partition tolerance 分区容忍性

定义:当出现网络分区后,系统能够继续“履行职责”。
分区容忍性没有要求分区发生时返回数据的正确性,也没有要求不能回复客户端错误消息,只有一个约束,就是「不能在分区时停机」。

Availability 可用性

定义:非故障的节点在合理的时间内返回合理的响应。
可用性并没有要求读到的数据的正确性,只描述了系统可以总可以非错的工作的能力。

节点故障时,我们是否可以仍然保证可用性?
方法是故障转移!!!

列举两种保可用性的方法,都是万变不离其宗地围绕着「故障转移」这个出发点。

1)一个方式是通过代理完成故障转移, 这就是工程上熟知的基于代理方式的负载均衡 (注:负载均衡的主要目的虽然是合理分配负载,但可用性也是其带来的好处之一)。当节点故障时,代理服务可以发现并暂时把节点从代理列表里踢出。

2)还有一种方式,我们甚至可以 配合客户端完成故障转移。 这就是另外一个工程上常用的负载均衡方案, 叫做「客户端侧的负载均衡」。客户端可以通过监测目标系统的服务器健康情况, 来决定向哪一个节点发起请求。

实践中,还可以通过减少人工维护造成的系统宕机、gracefully-shutdown、添加系统报警等手段来提高系统的可用性。

Consistency 强一致性

定义:对某个指定的客户端来说,读操作保证能够返回最新的写操作结果。
一致性可以理解为「正确性」。 具有一致性的系统, 写操作之后的读操作,必须返回该值。

CAP 的选择

在分布式环境下,我们会发现必须选择 P,因为网络本身无法做到 100% 可靠,所以分区是一个必然的现象。但「CP 或者 AP」 并不是绝对的选择题,CAP定理是我们在设计一个分布式系统之初时的一个有益参考, 它让我们在设计系统的时候不必浪费时间去寻求理论上都达不成的目标。

在实际中,一个分布式系统根本不可能完全放弃C、或者完全放弃A, 我们要做的是选择哪个多一点。

如果我们选择C多一些

为了实现更强的一致性,这个系统可能会在某些情况下拒绝服务、甚至直接关闭节点。 实例中,比较偏好C的有Zookeeper,Hbase,MongoDB等。

如果我们选择A多一些

为了实现更高的可用性,这个系统必须做好故障转移,尽可能地响应所有请求,但是有可能返回不一致的结果。 实例中,比较偏好A的是有Dynamo,CouchDB,Riak,Cassandra等。

没有绝对的选择和放弃,只有更偏好哪个和弱化哪个的说法。

话说, 我们可以做到CAP定理下的CA吗?

嗯!单点能 :)

本文参考至
1.https://writings.sh/post/cap-and-consistency-models
2.从0开始学架构-李运华