正确理解CAP定理

前言

  CAP的理解我也看了不少书籍,也看了很多同行的博文,基本每一个人的理解都不同,而布鲁尔教授得定义又太过的简单,没有具体描述和场景案例分析。所以本身参考部分资料梳理了一篇与你们互相分享一下。node

  标题写了正确理解,或许某些点不是百分百正确或者有歧义,可是但愿与各位分享讨论后达到最终正确web

简介

  CAP定理,又被称做布鲁尔定理(Brewer's theorem),是埃里克·布鲁尔教授在2000 年提出的一个猜测,它指出对于一个分布式系统来讲,不可能同时知足如下三点:redis

  • Consistency(一致性): where all nodes see the same data at the same time.(全部节点在同一时间具备相同的数据)
  • Availability(可用性): which guarantees that every request receives a response about whether it succeeded or failed.(保证每一个请求无论成功或者失败都有响应)
  • Partition tolerance(分隔容忍): where the system continues to operate even if any one part of the system is lost or fails.(系统中任意信息的丢失或失败不会影响系统的继续运做)

  不少书籍与文章引用Robert Greiner在2014年8月写的一篇博文 http://robertgreiner.com/2014/08/cap-theorem-revisited/。相比与看着布鲁尔教授一脸懵逼的定义,Robert Greiner的更加容易理解。sql

定义

原文: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)三者中的两个,另一个必须被牺牲。网络

关键字:interconnected nodes(互连节点)、share data(共享数据)、a write/read pair(读/写)session

  从上面一段话,有几个,也就是说咱们聊CAP定理的时候,是在具备数据读写、数据共享和节点互连的前提下,对上面三者选其二,也是建议咱们不要花费时间与精力同时知足三者。分布式

举例说明,web集群、memcached集群不属于讨论对象memcached

  • web集群只是资源复制分配在不一样的节点上,然而节点间没有互连、也没有数据共享(sessionid、memory cache)。
  • memcached集群数据存储是经过客户端实现哈希一致性,可是集群节点间不互连的,也没有数据共享。

总得来讲,CAP定理讨论的并非分布式系统全部的功能。翻译

一致性(Consistency)

原文:A read is guaranteed to return the most recent write for a given client.

翻译:对某个指定的客户端来讲,读操做保证可以返回最新的写操做结果

关键字:a given client(指定的客户端)。

  这里的一致性与咱们日常了解ACID的一致性有点误差,ACID的一致性关注的是数据库的数据完整性。

   上面定义没说明是全部节点必须在同一时间数据一致,而关注点在客户端,假若有个场景,您在ATM(客户端)往某张银行卡存500元后,马上在ATM发起查询余额的时候会显示加了500元后的余额,随后咱们也能把这500元取出来。查询余额读操做能够是写后马上读的主库,也或者写后某个时间段事后(中途无写)读从库。

可用性(Availability)

原文:A non-failing node will return a reasonable response within a reasonable amount of time (no error or timeout).

翻译:非故障节点将在合理的时间内返回合理的响应(不是错误或超时)。

关键字:non-failing node(非故障节点)、reasonable response(合理的响应)

  这里的可用性和咱们日常所理解的高可用性有点误差,高可用性指系统无中断的执行其功能的能力。

  已故障的节点就不具备可用性了,由于请求结果要么error要么 timeout。合理的响应没有说明是成功仍是失败,可是响应应该具备是否成功的精确描述。例如咱们读取sql server集群的某从库,同步须要时间,读取出来可能不是最新的数据,但倒是合理的响应。

分区容错性(Partition tolerance)

原文:The system will continue to function when network partitions occur.

翻译:当网络分区发生时,系统将继续正常运做

关键字:continue to function(继续正常运做)

  假如作了一个redis的一主两从的集群,某天某个从节点由于网络故障变成不可用,可是另外的一主一从仍然能正常运做,那么咱们认为它具备分区容错性。

CA-牺牲分区容错性

  做为分布式系统,分区必然总会发生(2年1次50分钟仍是1年3次共10分钟?),所以认为CAP的讨论是大部分创建在P确立前提下。假设咱们牺牲了P这个时候由于网络故障发生了分区致使节点不可用,这个时候请求响应了error、timeout,与可用性的定义相冲突了。

  可是,咱们又假如分区大部分时间是不存在的,这时对单节点的读\写,那么就无需做出C、A的取舍。可是上面说分区总会发生这不互相矛盾么,仍是取舍。假如1年时间内99.99%时间是正常的,不可用时间为0.01%(52.56分钟)不可用,若这个时间属于业务接受范围,或者只在某个地区(华南、华北、华中?)有影响,那么CA也是能够选择的。

PC-牺牲可用性

  最典型的案例是RDBMS集群与Redis集群,这两种都是利用主从复制实现读写分离的方案。假如二者都是创建一主多从的集群,在主节点写入数据,为了保证随后的读操做获取最新数据(一致性),这个读操做仍会请求主节点(读写分离的复杂点在从库同步不及时致使业务的异常,为了保证业务的正常性写后的读会请求主库),某个从节点挂了可是只要主节点和其余从节点仍然正常运做,就知足分区容错性。可是哪天主节点由于网络故障致使写操做的error或者timeout,那么这个系统就不可用了(牺牲可用性)。

这个时候能够引入其余功能和机制完成,例如Redis哨兵模式、故障转移功能。

PA-牺牲一致性

  最典型的案例是Cassanda集群和Riak集群,这种类型的分布式数据库,能够任意节点写入,任意节点读取,看成为集群出现,不管写入哪一个节点,都将会把该节点的数据同步到其余节点上,由于这种同步方式,读取数据时只要访问一个节点就足够了(喜欢任意访问也不拦着你),可是由于其余节点数据同步缘由,数据可能并非最新的(牺牲一致性)。若是当前节点由于网络异常致使分区变得不可用(不管读\写),能够转移访问节点(可用性)。

另外这里说的牺牲一致性,并不表明放弃一致性,而PA选择的是最终一致性(系统中全部的数据副本,在通过一段时间的同步后,最终可以达到一个一致的状态)

总结

  上面涉及“牺牲”字眼,并不表明非此即彼的选择,能够根据子系统、模块之间的设计上进行混搭使用(例如PA和PC、CA和PC)。

  本文对CAP定理作了一个简单的梳理描述,参考了部分书籍和文章加上本身的理解但愿能够跟你们作个分享,若是有不一样建议和见解包括文章内描述错误,请在下方评论指出,我将及时做出修改。

相关文章
相关标签/搜索