在分布式系统领域,CAP定理可谓鼎鼎大名,各类理解和解释颇多,今天,我也来聊聊本身的感觉。html
首先咱们先描述一下CAP定理的基本概念:算法
- 一致性(Consistency):每次请求均可以获得最新的数据。
对于单机系统而言,这一点彷佛很容易保证,好比咱们更新的单机数据库中的一条记录以后不管怎么读取数据,都能获得更新以后的最新数据【注1】。sql
可是对于一个有多个节点的分布式系统,状况就没有这么简单了,通常状况下节点之间的数据是经过“复制”的方式来同步的,假设你更新系统中某一节点的一条数据,对数据的更新操做会复制到系统的其余节点,可是复制有一个“窗口期”,也就是说一个节点的更新复制到另外一个节点上须要必定的时间,在“窗口期”时间以内,请求到复制没有完成的节点返回的数据就会产生不一致状况。mongodb
理论上,咱们减少“窗口期”时间就能够下降不一致发生的几率,可是“窗口期”永远不可能为零,及时节点“复制”达到了光速,即便使用了量子纠缠也不能让复制行为达到“同步”,因此完美的一致性在这个宇宙是不存在的只存在于神话中。数据库
- 可用性(Availability):每次请求均可以获得一个响应,可是获得的数据不必定是最近的数据。
对于一个要持续可用的分布式系统,每个非故障的节点必须对每个请求做出响应。也就是说,服务使用的任何算法都必须最终终止,当同时要求分区容忍性时,这是一个很强的定义:即便是严重的网络错误,每一个请求必须终止。这里须要注意发生故障且没法响应客户请求的节点,并不会致使失去这里所述的“可用性”。网络
可用性保证每次请求都能获得响应,即便某些节点挂了,系统依然要响应请求。这点对于分布式系统相当重要,咱们不能保证系统中众多节点在运行期间总体可用,总会出现不可用的状况,好比节点崩溃、节点数据异常、节点链接超时等,因此咱们要保证某些节点不可用的状况下系统依然可用。架构
虽然咱们可用经过添加节点避免单点故障来提高整个系统的可用性,可是显而易见的是咱们依然不能保证100%可用,咱们只能提高小数点后九的位数(99.999...%)。因此绝对的可用是没法达到的,话说只要一说“绝对”好像都不靠谱。nosql
- 分区容错性(Partition tolerance):当系统中有节点因网络缘由没法通讯时,系统依然能够继续运行。
分布式系统由多个节点组成,节点间的网络通讯老是不可靠的,全部咱们老是要保证分布式系统节点间产生网络分区的状况下,这样分布式系统才有存在的意义。分布式
这里须要注意的是,节点故障是否属于网络分区?这个问题确实容易让人产生误解。假设咱们有一个由三个节点组成的系统,其中一个节点down了,若是咱们认为这种状况下产生了网络分区,那么咱们只能在可用性和一致性作出选择。可是咱们发现根据可用性定义,故障的节点并不影响可用性,并且故障节点已经不会相应任何请求了,其余节点能够很容易地进行补偿(例如主备模式),弥补了可用性和一致性。因此若是节点故障属于网络分区,咱们就获得一个违背CAP定理的结论——C、A、P咱们能够同时保证。至此咱们从反面证实了网络故障不属于网络分区。ide
可用性容易与分区容错性相混淆,这两个概念都是保证系统能够持续对外提供服务。可是两个概念侧重点不一样,可用性是保证系统中某些节点故障的状况下系统可用,而分区容错性是保证系统出现网络分区即某些节点相互通讯失败的状况下,系统依然可用。
CAP定理定义了这三个属性之间的相互关系:根据定理,分布式系统只能知足三项中的两项而不可能知足所有三项。这样就产生三种取舍状况:CA(withoutP)、CP(withoutA)、AP(withoutC)。
如今互联网应用的场景中,系统节点众多,节点之间网络异常不可避免,因此要保证系统正常运行必须保证分区容错性,那根据CAP定理,就要在可用性和一致性间作出选择,从实际业务的角度上,这种选择更像是一种权衡,就是说咱们更倾向于可用性多一些或者更倾向于一致性多一些。
传统数据库的分布式事务大多采用这种模式,众所周知XA事务最大的缺点就在于超时问题上,若是对一个资源管理器的事务提交操做由于网络缘由等待,参与分布式事务其余节点都须要等待延时节点,导致系统变慢并最终致使不可用。
MySQL主从复制模式就是典型的AP应用场景,当主从节点产生网络延时导致从节点数据不能及时同步时,咱们无需等待网络恢复,依然能够继续访问从节点获取数据。
在当下互联网业务场景中,咱们更多的时候是在可用性和一致性之间作出选择。在实际的业务中,单纯保证一致性不但没法达到也会严重的影响系统的效率,同理可证,想要绝对的可用性也是不现实的,任何业务流程也不会容许大量的非一致性数据出现,这样就形成了总体业务逻辑失败。分布式系统的可用性和一致性就如同太极阴阳两面,你中有无,我中有你,做为架构师咱们努力在业务场景寻找一致性和可用性的平衡点,对于架构师而言,“最”不重要,“合适”更好。
注1:单机系统依然会产生一致性问题,只是与CAP中一致性不是一个问题,故不在此展开。
注2:这里还有一种状况比较特殊,这种状况是“CA”集群,这种集群极少发生网络分区状况,且一旦发生分区,就让分区中的全部节点中止工做。这样操做至关于舍弃了有问题节点,系统中其余正常节点就不存在分区问题了。咱们并无在存在分区的系统中继续工做,咱们很粗暴的解决了网络分区的状况。从某种意义上说,这是能够实现的,可是实现起来很是麻烦,须要实时监控系统中节点是否出现网络分区而且在一旦出现分区便可将分区内的节点所有下线。说到这里你必定有一个疑惑,若是咱们将节点下线的难道不会影响CA中的可用性吗?根据可用性定义可知,故障节点并不影响可用性,由于可用性须要保证非故障节点有响应。因此此处将分区节点下线以解决分区问题并不会影响可用性。
参考:
https://zh.wikipedia.org/wiki...
https://en.wikipedia.org/wiki...
http://www.runoob.com/mongodb...
http://www.hollischuang.com/a...
https://stackoverflow.com/que...
http://blog.nahurst.com/visua...
https://codahale.com/you-cant...
http://www.jdon.com/artichect...
http://www.jdon.com/46956《NoSQL精粹》