概念:
CAP定理即分布式系统最多同时满足 C、A、P 中的两个。
一致性(Consistency):所有节点在同一时间的访问到的数据完全一致。
可用性(Availability):请求在一定的响应时间内可以被应答。
分区容忍性(Partition tolerance):分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性或可用性的服务。(说人话就是,在系统出现故障的时候仍然可以提供服务)
理解:
为什么 C、A、P 之间不能同时满足?
解释一下分区这个概念,首先什么是分区呢?在分布式系统中存在多个节点,在这些节点之间网络是畅通的,但是当某些节点与其他节点的通信被某种原因阻断之后,这时候,系统分成了若干个互不联通的区域,此时就形成了分区。而数据就分别存储于这些分区之中。当系统需要访问分区中某个节点的数据时,由于分区之间互不联通,系统是无法成功访问到数据的,也就无法提供可用性,此时系统的分区容忍性差。
通常,我们为了避免这种情况的发生,一般采用将数据复制到多个节点上的做法来提高分区容忍性,这样当分区中的节点数据不可用时,可以转而访问其他分区复制节点中的数据。但是,这种做法也并不是一劳永逸的。因为当数据发生更新时,不同分区中节点的数据可能就会不同步,此时系统就无法提供一致性。那么在这种情况下有什么办法来保证一致性吗?比如通过设置读写锁,在每次写入数据后,确保每个节点的数据都更新之后才可以进行读取。事实上,这样的方法确实存在,也确实可行,但却是以牺牲了可用性为代价的(因为在这个等待写入的过程中,可能由于等待时间过长而得不到响应,这样就会带来可用性的问题)。故而,当我们满足可用性的时候,它是默认以存在分区为前提的,所以就已经满足了一部分的分区容忍性,同理,满足一致性的时候,也已经满足了一部分的分区容忍性。
关于为什么现在大部分 NoSQL 系统中普遍采用牺牲一致性的做法?
根据 CAP 理论来看,是可以在 C、A、P 三者之间两两任意排列组合的,那为什么不普遍放弃 P 或者 A 呢?如果放弃分区容忍性,选择满足可用性和一致性,这在没有产生网络分区的情况下是可行的(在这种情况下,节点的数据是同步的,而且可以访问并得到响应),但是由于分布式系统中分区是无法控制的,而一旦产生了分区,那么一致性和可用性之间就无法同时满足,而且正是由于网络分区不可控,所以分区容忍性也是必须要考虑的。那么我们只能在可用性和一致性之间做出权衡。
如果选择牺牲可用性,那么每次读取数据都必须经过长时间的等待数据同步的过程,而且由于分区的存在,这个同步时间可能会很长,这对于用户体验是非常不利的。但是选择牺牲一致性的话,对于某些特殊场景,例如股票金融市场影响会比较大之外,其余应用环境似乎也不是不能接受弱一致性(举一个网上的例子:a 在 b 的博客上评论,由于弱一致性的存在,a 可以马上看到自己评论的评论信息,但是 b 在等待十几秒后才看到评论信息,在这个场景中是可以被接受的)。目前,大部分的 NoSQL 都是采用了最终一致性,即不保证任意时间段的数据是同步的,只保证其最终的结果趋向于一致,最终一致性属于弱一致性的特例,其本质就是相当于牺牲一部分一致性,换取高可用性和高分区容忍性。
参考资料:
[1].CAP理论中的P到底是个什么意思? - 知乎 https://www.zhihu.com/question/54105974
[2].Scalable SQL and NoSQL Data Stores,Rick Cattell,2011.
[3].Rethinking Eventual Consistency,Philip A. Bernstein,Sudipto Das,2013.
[4].Eventual Consistent Databases: State of the Art,Mawahib Musa Elbushra, Jan Lindström,2014.