昨天看了一篇CAP定理的文章,觉得讲的很形象,原文地址:http://www.ruanyifeng.com/blog/2018/07/cap.html
好记性不如烂笔头,也把自己的理解记录一下。
一、什么是CAP
CAP理论是分布式系统中非常重要的一个概念。这里注意点是 ‘分布式系统’,也就是说单机系统中是没有CAP这种概念的。
分布式系统最大的难点就是各个节点的状态如何同步,比如各节点数据如何同步。CAP 定理是这方面的基本定理,也是理解分布式系统的起点。
什么是CAP?
- C:Consistency 一致性 (与数据库的事务特性ACID中C是相识的,因为有一篇文章是说数据库的一致性是内一致性,分布式的一致性是外一致性,总体来都是一致性)
- A:Availability 可用性
- P:Partition-tolerance 分区容错性
在这个三个指标中,只能同时满足两个,不可能同时满足三个。

二、Partition-tolerance
分区容错性。为什么首先要说分区容错性呢?
大多数的分布式系统都分布有多个子网络,每一个子网络就叫做一个区,各个区之间的通信有可能失败。比如,一台服务器在中国,一台服务器在美国,这就相当于两个区,它们之间的通信就有可能失败。

如上图,客户端向G1发送一条消息,各个节点之间数据要进行同步,此时G1把消息发给G2,此时通信可能会失败,这就是分区容错。一般在分布式系统中,CAP中的P总是要被满足的,也就是要保证各个节点之间的相互通信。
三、Consistency
一致性。分布式系统中有多个节点,就是要保证各节点之间数据的一致性。
客户端在G1中修改了某条数据,此时可能通过负载均衡客户端在G2中查询这条数据,你要保证查到的数据是修改之后的。

但问题就在于,用户在某节点修改数据,而查询数据是在另外节点上,如何保证返回的结果是一致的呢?如果读的操作不一致,那就不满足一致性。

为了使得G2节点的信息是最新的,那么在G1修改数据之后,需要G1向G2发送一条消息,要求G2也修改这条数据。
这样即使用户写是在G1,读在G2,也能保证读到是一致的。
其实这里还有一个问题就是:G1 再 向G2发送修改的过程中,也就是还未修改,此时如果有用户查询在怎么办?
四、Availability
可用性。也就是需要保证节点是可用的,用户向节点发送消息,节点能够返回给用户信息。用户可以选择向 G1 或 G2 发起读操作。不管是哪台服务器,只要收到请求,就必须告诉用户,到底是 v0 还是 v1,否则就不满足可用性。
五、一致性和可用性之间的矛盾
为什么会说这两者之间会有相互矛盾呢?一致性和可用性,不可能同时成立,因为可能会出现通信失败,即分区容错。
举个例子:
如果需要保证G2的数据一致性,那么需要在G2也需要同步G1的状态,那么在G1写操作的同时,需要锁定G2的读操作和写操作,只有数据同步之后,才能放开G2的锁。这就造成了,在锁定期间,G2是不能操作的,因为要保证数据一致,你都不能操作了,你还有可用性?
如果要保证G2的可用性,那么在数据同步的时候,就不能对G2加锁,这就造成了其他用户可以对G2进行操作,可能会造成数据的不一致性。
综上所述,G2不能同时做到一致性和可用性,系统设计时只能选择一个目标。如果追求一致性,那么无法保证所有节点的可用性;如果追求所有节点的可用性,那就没法做到一致性。
那么场合可用性高于一致性呢?
一般来说,网页的更新不是特别强调一致性。短时期内,一些用户拿到老版本,另一些用户拿到新版本,问题不会特别大。当然,所有人最终都会看到新版本。所以,这个场合就是可用性高于一致性。
可以这么理解,如果分布式系统涉及到必须要满足一致性,比如涉及到转账业务,交易相关的,那就必须满足一致性。但是如果即使用户此时获取到的信息不是最新的也能满足用户需求,最终能达到一致性,那么此时使用可用性。