一、为什么分布式系统要么是 CP 要么是 AP 呢?

1、分布式系统:分布式系统是一个硬件或软件组件分布在不同的网络计算机上,彼此之间仅仅通过消息传递进行通信和协调的系统。

2、从分布式系统的定义可知,分布式是建立在网络之上的,既然有网络,那么肯定会存在网络出现问题的情况,那意味着我们在设计分布式系统的时候,必须要考虑的一个点就是:如果网络出现了问题,那么我们的系统应该怎么做。

3、分区:一个分布式系统里面数据存储在各个节点里面,节点组成的网络正常情况下都是连通的。如果因为一些故障导致有些节点之间无法连通,则整个网络就分成了几个区域,这些不连通的区域就是分区。

4、当我们的数据只在系统中某一个节点中保存,那么当分区出现后,那么这个不连通的节点上面保存的数据就无法被用户访问了,这叫做分区无容错性,给用户的直观感觉就是数据丢了或者数据无法写入了,这要比看到不是最新的数据要严重的多。

5、那么提高分区容忍性的办法就是同时存在多个节点保存同一份数据,这样当分区出现之后,这一份数据项就可能在多个分区里面存在,容错性就提高了。

6、如果要把数据复制到多个节点,带来的问题就是一致性,就是多个节点上面的数据可能是不一致的。要保证一致,每次写操作就都要等待全部节点写成功,而这等待又会带来可用性的问题,也即一段时间内,系统是不可读的。

二、CAP 的解释

image.png

1、一致性(Consistency)

Consistency 中文叫做”一致性”。意思是,写操作之后的读操作,必须返回该值。即等同于所有节点访问同一份最新的数据副本

  • 举例来说,某条记录是 v0,用户向 G1 发起一个写操作,将其改为 v1。

image.png

  • 接下来,用户的读操作就会得到 v1。这就叫一致性。

image.png

  • 问题是,用户有可能向 G2 发起读操作,由于 G2 的值没有发生变化,因此返回的是 v0。G1 和 G2 读操作的结果不一致,这就不满足一致性了。

image.png

  • 为了让 G2 也能变为 v1,就要在 G1 写操作的时候,让 G1 向 G2 发送一条消息,要求 G2 也改成 v1。

image.png

  • 这样的话,用户向 G2 发起读操作,也能得到 v1。

image.png**

2、可用性(Availability)

每次请求都能获取到非错的响应**,但是不保证获取的数据为最新数据。**用户可以选择向 G1 或 G2 发起读操作。不管是哪台服务器,只要收到请求,就必须告诉用户,到底是 v0 还是 v1,否则就不满足可用性。

3、分区容错性(Partition tolerance)

image.png
上图中,G1 和 G2 是两台跨区的服务器。G1 向 G2 发送一条消息,G2 可能无法收到。系统设计的时候,必须考虑到这种情况。

一般来说,分区容错无法避免,因此可以认为 CAP 的 P 总是成立。CAP 定理告诉我们,剩下的 C 和 A 无法同时做到。

大多数分布式系统都分布在多个子网络。每个子网络就叫做一个区(partition)。分区容错的意思是,区间通信可能失败。比如,一台服务器放在中国,另一台服务器放在美国,这就是两个区,它们之间可能无法通信。以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在 C 和 A 之间做出选择,保证分布式网络中部分网络不可用时, 系统依然正常对外提供服务。

三、Consistency 和 Availability 的矛盾

一致性和可用性,为什么不可能同时成立?答案很简单,因为可能通信失败(即出现分区容错)。

如果保证 G2 的一致性,那么 G1 必须在写操作时,锁定 G2 的读操作和写操作。只有数据同步后,才能重新开放读写。锁定期间,G2 不能读写,没有可用性不。

如果保证 G2 的可用性,那么势必不能锁定 G2,所以一致性不成立。

综上所述,G2 无法同时做到一致性和可用性。系统设计时只能选择一个目标。如果追求一致性,那么无法保证所有节点的可用性;如果追求所有节点的可用性,那就没法做到一致性。

读者问,在什么场合,可用性高于一致性?
举例来说,发布一张网页到 CDN,多个服务器有这张网页的副本。后来发现一个错误,需要更新网页,这时只能每个服务器都更新一遍。
一般来说,网页的更新不是特别强调一致性。短时期内,一些用户拿到老版本,另一些用户拿到新版本,问题不会特别大。当然,所有人最终都会看到新版本。所以,这个场合就是可用性高于一致性。

四、分布式与集群

1、分布式(distributed)是指在多台不同的服务器中部署不同的服务模块,通过远程调用协同工作,对外提供服务。

2、集群(cluster)是指在多台不同的服务器中部署相同应用或服务模块,构成一个集群,通过负载均衡设备对外提供服务。