在弄清楚这个问题以前,咱们先了解一下什么是分布式的CAP定理。node
根据百度百科的定义,CAP定理又称CAP原则,指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),最多只能同时三个特性中的两个,三者不可兼得。数据库
1、CAP的定义
Consistency (一致性):服务器
“all nodes see the same data at the same time”,即更新操做成功并返回客户端后,全部节点在同一时间的数据彻底一致,这就是分布式的一致性。一致性的问题在并发系统中不可避免,对于客户端来讲,一致性指的是并发访问时更新过的数据如何获取的问题。从服务端来看,则是更新如何复制分布到整个系统,以保证数据最终一致。网络
Availability (可用性):架构
可用性指“Reads and writes always succeed”,即服务一直可用,并且是正常响应时间。好的可用性主要是指系统可以很好的为用户服务,不出现用户操做失败或者访问超时等用户体验很差的状况。并发
Partition Tolerance (分区容错性):分布式
即分布式系统在遇到某节点或网络分区故障的时候,仍然可以对外提供知足一致性或可用性的服务。.net
分区容错性要求可以使应用虽然是一个分布式系统,而看上去却好像是在一个能够运转正常的总体。好比如今的分布式系统中有某一个或者几个机器宕掉了,其余剩下的机器还可以正常运转知足系统需求,对于用户而言并无什么体验上的影响。架构设计
2、CAP定理的证实
如今咱们就来证实一下,为何不能同时知足三个特性?设计
假设有两台服务器,一台放着应用A和数据库V,一台放着应用B和数据库V,他们之间的网络能够互通,也就至关于分布式系统的两个部分。
在知足一致性的时候,两台服务器 N1和N2,一开始两台服务器的数据是同样的,DB0=DB0。在知足可用性的时候,用户不论是请求N1或者N2,都会获得当即响应。在知足分区容错性的状况下,N1和N2有任何一方宕机,或者网络不通的时候,都不会影响N1和N2彼此之间的正常运做。
当用户经过N1中的A应用请求数据更新到服务器DB0后,这时N1中的服务器DB0变为DB1,经过分布式系统的数据同步更新操做,N2服务器中的数据库V0也更新为了DB1,这时,用户经过B向数据库发起请求获得的数据就是即时更新后的数据DB1。
上面是正常运做的状况,但分布式系统中,最大的问题就是网络传输问题,如今假设一种极端状况,N1和N2之间的网络断开了,但咱们仍要支持这种网络异常,也就是知足分区容错性,那么这样能不能同时知足一致性和可用性呢?
假设N1和N2之间通讯的时候网络忽然出现故障,有用户向N1发送数据更新请求,那N1中的数据DB0将被更新为DB1,因为网络是断开的,N2中的数据库仍旧是DB0;
若是这个时候,有用户向N2发送数据读取请求,因为数据尚未进行同步,应用程序没办法当即给用户返回最新的数据DB1,怎么办呢?有二种选择,第一,牺牲数据一致性,响应旧的数据DB0给用户;第二,牺牲可用性,阻塞等待,直到网络链接恢复,数据更新操做完成以后,再给用户响应最新的数据DB1。
上面的过程比较简单,但也说明了要知足分区容错性的分布式系统,只能在一致性和可用性二者中,选择其中一个。也就是说分布式系统不可能同时知足三个特性。这就须要咱们在搭建系统时进行取舍了,那么,怎么取舍才是更好的策略呢?
3、取舍策略
CAP三个特性只能知足其中两个,那么取舍的策略就共有三种:
CA without P:若是不要求P(不容许分区),则C(强一致性)和A(可用性)是能够保证的。但放弃P的同时也就意味着放弃了系统的扩展性,也就是分布式节点受限,没办法部署子节点,这是违背分布式系统设计的初衷的。
CP without A:若是不要求A(可用),至关于每一个请求都须要在服务器之间保持强一致,而P(分区)会致使同步时间无限延长(也就是等待数据同步完才能正常访问服务),一旦发生网络故障或者消息丢失等状况,就要牺牲用户的体验,等待全部数据所有一致了以后再让用户访问系统。设计成CP的系统其实很多,最典型的就是分布式数据库,如Redis、HBase等。对于这些分布式数据库来讲,数据的一致性是最基本的要求,由于若是连这个标准都达不到,那么直接采用关系型数据库就好,不必再浪费资源来部署分布式数据库。
AP wihtout C:要高可用并容许分区,则需放弃一致性。一旦分区发生,节点之间可能会失去联系,为了高可用,每一个节点只能用本地数据提供服务,而这样会致使全局数据的不一致性。典型的应用就如某米的抢购手机场景,可能前几秒你浏览商品的时候页面提示是有库存的,当你选择完商品准备下单的时候,系统提示你下单失败,商品已售完。这其实就是先在 A(可用性)方面保证系统能够正常的服务,而后在数据的一致性方面作了些牺牲,虽然多少会影响一些用户体验,但也不至于形成用户购物流程的严重阻塞。
3、总结
现现在,对于多数大型互联网应用的场景,主机众多、部署分散,并且如今的集群规模愈来愈大,节点只会愈来愈多,因此节点故障、网络故障是常态,所以分区容错性也就成为了一个分布式系统必然要面对的问题。那么就只能在C和A之间进行取舍。但对于传统的项目就可能有所不一样,拿银行的转帐系统来讲,涉及到金钱的对于数据一致性不能作出一丝的让步,C必须保证,出现网络故障的话,宁肯中止服务,能够在A和P之间作取舍。
总而言之,没有最好的策略,好的系统应该是根据业务场景来进行架构设计的,只有适合的才是最好的。
————————————————版权声明:本文为CSDN博主「鄙人薛某」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处连接及本声明。原文连接:https://blog.csdn.net/yeyazhishang/article/details/80758354