1、CAP理论
作为分布式系统的基础理论,它描述的是一个分布式系统在以下三个特性中:
一致性(Consistency)
可用性(Availability)
分区容错性(Partition tolerance)
最多满足其中的两个特性。也就是下图所描述的。分布式系统要么满足CA,要么CP,要么AP。无法同时满足CAP。
分区容错性
:这个概念要仔细讲解
- 什么是分区?一个分布式系统里面,节点组成的网络本来应该是连通的。然而可能因为一些故障,使得有些节点之间不连通了,整个网络就分成了几块区域。数据就散布在了这些不连通的区域中。这就叫分区,分区其实就是一种故障情况
- 分区会造成什么影响?当你一个数据项只在一个节点中保存,那么分区出现后,和这个节点不连通的部分就访问不到这个数据了,这样就会造成应用程序的局部瘫痪甚至是全局瘫痪,这种情况下分区是致命的
- 分区容错性是什么?意思就是容忍和承受分区这种故障的能力。
- 如何提高分区容忍性?可以将一个数据项复制到多个节点上,那么出现分区之后,这一数据项就可能分布到各个区里。容忍性就提高了
可用性
: 一直可以正常的做读写操作。简单而言就是客户端一直可以正常访问并得到系统的正常响应。用户角度来看就是不会出现系统操作失败或者访问超时等问题。
一致性
:在分布式系统完成某写操作后任何读操作,都应该获取到该写操作写入的那个最新的值。相当于要求分布式系统中的各节点时时刻刻保持数据的一致性。
2、为什么没有系统能同时满足CAP?
如果我们事先保证了分区容错性,也意味着若某个节点故障了,用户还是可以继续访问。这时用户在访问过程中就会出现一致性和可用性不能同时满足的情况,参考下图
如图假设分布式系统有G1,G2两个节点,初始值都是v0。现在有一个client向系统写入了值v1,这里假设直接写的是节点G1,G1数据同步到G2的过程中出现了故障,G1节点上的数据还未同步到G2节点,因此客户端读取到的是修改之前的值v0。 这就出现了不满足一致性的情况了。相当于满足了可用性,失去了一致性。
类似的,如果系统保证了强的一致性
那么在client 写完G1节点后, 而G1向G2节点同步数据出现了问题后,client再去读取G2节点的数据时就会一直处于等待状态。这就相当于满足了一致性,而失去了可用性。
考虑多个客户端访问时,一致性和可用性还可以这么理解:假如client1 向G1 修改某个值的时候, 写操作还未完成,client2就发起来对该值的读操作,读的是G2节点,这时如果要满足一致性,那么就得让client2 暂时无法使用,如果要让client2 使用,那么获取到的数据不是最新的,系统就不满足一致性。
总结:要把数据复制到多个节点,就会带来一致性的问题,就是多个节点上面的数据可能是不一致的。要保证一致,每次写操作就都要等待全部节点写成功,而这等待又会带来可用性的问题。总的来说就是,数据存在的节点越多,分区容忍性越高,但要复制更新的数据就越多,一致性就越难保证。为了保证一致性,更新所有节点数据所需要的时间就越长,可用性就会降低。所以CAP最多满足其中的两个
3、CAP三者不可兼得,该如何取舍
(1) CA: 优先保证一致性和可用性,放弃分区容错。 这也意味着放弃系统的扩展性,系统不再是分布式的,有违设计的初衷。
(2) CP: 优先保证一致性和分区容错性,放弃可用性。在数据一致性要求比较高的场合(譬如:zookeeper,Hbase) 是比较常见的做法,一旦发生网络故障或者消息丢失,就会牺牲用户体验,等恢复之后用户才逐渐能访问,例如银行微信支付宝转账,对数据准确性要求较高时要满足CP
(3) AP: 优先保证可用性和分区容错性,放弃一致性。NoSQL中的Cassandra 就是这种架构。跟CP一样,放弃一致性不是说一致性就不保证了,而是数据慢慢的更新。例如双十一某火爆商品的实时销量,要满足AP,毕竟,总不能因为实时销量更新不及时就反馈给用户一个异常界面把,那明天的新闻头条就有的写了,至于实时销量,慢慢更新也无妨!