CAP 定理(CAP theorem)。
定理(英语:Theorem)是经过受逻辑限制的证明为真的陈述。 一般来说,在数学中,只有重要或有趣的陈述才叫定理。 证明定理是数学的中心活动。CAP是被证明出来的,但是也许未来会被打破。
趁着还没有被打破,我们赶紧学习一下。
Any distributed system cannot guaranty C, A, and P simultaneously 对于一个分布式计算系统,不可能同时满足一致性(Consistence)、可用性(Availability)、分区容错性(Partition Tolerance)三个设计约束。 In a distributed system (a collection of interconnected nodes that share data.), you can only have two out of the following three guarantees across a write/read pair: Consistency, Availability, and Partition Tolerance - one of them must be sacrificed. 在一个分布式系统(指互相连接并共享数据的节点的集合)中,当涉及读写操作时,只能保证一致性(Consistence)、可用性(Availability)、分区容错性(Partition Tolerance)三者中的两个,另外一个必须被牺牲。
从上文中我们可以看出第二版是更加详细和明确的:
我觉得我们应该 理解一下什么是分布式系统:分布式系统是多个处理机通过通信线路互联而构成的松散耦合的系统(百度百科)。对于memorycache集群来讲他并不用考虑一致性,因为他的存储本来就是不相关不胡通的,所以是不是根本就不存在一致性这么一说呢?但是在这里我们是不是可以在思考一下是不是两个作者对分布式系统的概念存在偏差呢,也不能说第一版是不严谨的呢? 但是想从文字上讲第二版的确是很详细。
All nodes see the same data at the same time. 所有节点在同一时刻都能看到相同的数据。 A read is guaranteed to return the most recent write for a given client. 对某个指定的客户端来说,读操作保证能够返回最新的写操作结果。
第一版从文字字面意思只描述了读,但是对于各个几点来讲要读一致,那必须写的时候也不会影响了。如果要深久这句话的话,我们平时在分布式系统中我们是有事物控制机制的,这个时候对于相同线程和不同线程之间都是不一致的,更别说我们所有节点之间的数据一致了。我觉得这样讲实在抬杠,因为刚也说了不同的线程之间,如果在这个修改数据的节点再去起一个线程查看那其实也是一致的。
对于第二版描述了一个场景,有客户端有读有写,对于上面描述的场景是更加详尽了。只能说又一次描述的更加清楚了。
Every request gets a response on success/failure. 每个请求都能得到成功或者失败的响应。 A non-failing node will return a reasonable response within a reasonable amount of time (no error or timeout). 非故障的节点在合理的时间内返回合理的响应(不是错误和超时的响应)。
第一版的可用性描述,因为太广义了,以导致我真的有点都不能理解,对于一个系统挂掉了,那每一个请求都是返回失败的响应,那是不是可以符合第一版本的概念呢?所以这个成功和失败是业务意义上的,一次请求我因为参数校验没过返回了失败。这个失败才是第一版本所说的失败。成功指的是走完了整个处理的逻辑。第二个版本部得不说是确实更加详细也更容易理解了。有服务挂掉了,但是还是仍然存在正常的正常的节点,这些节点会在我们规定的超时时间内正确的处理请求,这里的正确指的是符合预期的执行计划。
总而言之,有机器挂掉的时候,我们的服务可以正确(非严格意义上的正确)的返回数据。
System continues to work despite message loss or partial failure. 出现消息丢失或者分区错误时系统能够继续运行。 The system will continue to function when network partitions occur. 当出现网络分区后,系统能够继续“履行职责”。
其实对于我这个经验不多且基础不扎实的程序员来讲,这两句都很难懂。那我试着拆开理解一下,出现消息丢失,比较好理解,分区错误怎么理解呀 我们先来理解下分区:一个分布式系统里面,节点组成的网络本来应该是连通的。然而可能因为一些故障,使得有些节点之间不连通了,整个网络就分成了几块区域。数据就散布在了这些不连通的区域中。这就叫分区。 那么既然产生了分区,那么这个时候客户端请求就会出现数据不一致,导致客户端就会出现非预期内的结果。怎么才能继续运行呢,那就是就算产生分区,那也能让各个分区间的数据都能通过复制同步起来。牵扯到数据复制就会有一致性问题,因为有些节点有可能成功,也有可能失败。为了一致性那么我们只能强制写所有节点,强制写所有节点,那这岂不知又有可用性的问题 ,写所有节点需要时间呀,需要时间后就有可能超时呀。。。。。。扯远了 ,等会继续聊三者之间的关系和应用。继续聊分区容错性,我们回到第一版本 ,其实这句话本身是有问题的,因为我们聊了分区产生原因是出现网络丢包或者丢消息导致的分区,所以他两是一个因果关系,而不是并列关系。第二版本就爽朗多了。
总而言之,当因为网络等问题导致产生分区后,我们的系统能履行职责就是分区容错性。(这个职责非严格意义上的容错)
CAP理论是 CAP 不能同时存在,那这原因是什么呢?
首先分布式系统是多节点的,多节点之间需要保证一致性,以写一条数据为例,首先得保证所有写都成功。既然写都得成功,又因为我们的节点的网络并不是100%可靠的,自然灾害,有人偷电缆,停电等等导致我们的网络不可用等等,那这个时候并不能保证每个机器都写到。有可能你会说了,我等呀他总有恢复的时候,等个屁你能等用户等不了。服务是有超时时间的。如果真的等,那这个可用性就不能保证了。首先我们是确定了CA 肯定是不能保证的。
那这个CP呢,一致性和分区容错性,依然以写数据为例,还是遇到了同样的问题,出现网络问题导致丢消息产生了分区,但是我们的分区之间是有复制机制的,这个复制并且是异地多活的可以99.99999999999%(没有绝对的事情)可以分区容错,并且也保证了最终的一致性,但是可用性就不能保证了,因为在复制的过程中会有一些超时请求。
那么AP呢,可用性和分区容错性,其实更容易理解了,当产生了分区后,我们不用很care这个一致性。不能复制到其他分区也没事,我不在乎。我只保证每次请求过来逗呢能够给用户返回非错误超时的返回就ok。
上面在描述 AP的时候有讲非严格意义上的正确, 我对这句话的解释:如果你是AP架构产生不一致对于你的业务逻辑定义来讲出现了不一致是不正确的,但是对于架构层面却是正确的。对于CP来阿静 出现少量不可用对于业务来讲这是不对的,但是对于架构来讲这是正确的。