分布式系统的CAP理论
CAP理论是指分布式系统架构中通常只能够满足CAP三个指标中的两个,而不能同时满足CAP三个指标
C(Consistency):一致性 一致性指的是All nodes see the same data at the same time,也就是说所有节点在同一时间看到的数据必须是一模一样的,比如足球比赛中,当比分发生了改变,客户端A看到的比分是1:0,而客户端B看到的比分还是0:0;又比如在银行系统中,通过微信进行银行卡转账,卡上余额从100变成了0,但是在支付宝中查看银行卡余额还是100,这显然就破坏了数据的一致性。
A(Avalilability):可用性 可用性指的是Reads and writes always succeed,也就是说无论是读操作还是写操作,始终是成功的,也就是服务一直可用,不存在服务失败或者用户操作失败的情况。比如说用户发起提现操作,过了会显示提现失败;在进行转账的时候提示了需要等2天后才能到账,显然就破坏了可用性,因为用户的一系列操作换来的是提现失败,转账延迟才能到账,而不是立马响应到账。
P( Partition Toleranc):分区容错性 分区容错性指all nodes look like one node,也就是说多个节点的运行看起来就像是一个节点在运行一样,一个节点宕机不可用,其他节点还可以正常运行。比如说某个应用程序在全国各地部署了10个节点,如果青岛的节点宕机了,从而导致其他9个节点也不可用,这显然对于分布式系统来说是灾难性的,所以分布式的CAP的最先需要保证的也就是P,因为如果连P都实现不了,那么分布式就没啥意义了,因为部署多个节点除了分担单节点的压力之外,就是需要解决单节点宕机的情况下,其他节点可以继续提供正常的服务。
CAP三个指标无法共存。 古有一山不容二虎,也有鱼与熊掌不可兼得。但是这里涉及到的是三个对象。那么就可以用另外一个故事来描述,那就是一个和尚挑水吃,两个和尚抬水吃,三个和尚没水吃(没有关联,只是形容下CAP理论完成1个和2个指标很容易,但是无法同时实现三个指标) 那么为什么三个指标无法同时满足呢?看下面一个例子。
服务A和服务B,服务A数据x=0,服务B数据x=0,初始状态服务A和服务B都获取数据x=0,此时服务A将x的值更新成了1,而服务B此时的x还是等于0, 如果需要满足一致性,那么必须要在服务A更新本身数据的同时通知服务B也进行更新; 如果需要满足可用性,那么在用户调用服务A执行更新x值的时候就必须立刻返回更新成功的操作 如果需要满足分区容错性,就必须保存服务A和服务B任何一方异常了,不会影响服务的正常提供
那么如果出现服务A在通知服务B进行同步更新x的值的时候出现了网络异常会怎么样? 当服务A更新了x值之后,服务A和服务B之间网络异常无法及时通知服务B也就行x值的更新,而此时用户B来调用服务B的查询x值的操作。 如果需要满足一致性:那么服务B此时就不能立即给用户B返回x值,因为服务B的值是旧的,还没有更新成新的,那么就需要阻塞,知道网络正常之后再更新x值,此时就破坏了可用性,因为用户B的查询操作失败了或者是需要等待过长时间。 如果需要满足可用性:那么用户B调用服务B查询x值的时候就需要立即返回x值,也就是x=0的值,而此时服务A已经将x的值改成1了,所以就破坏了一致性的原则。 如果需要同时满足一致性和可用性,当服务A和服务B之间的通信出现异常时,就需要将整个服务设置成不可用,这样用户就不会在调用服务,数据也可在同步之后保持一致,但是也就破坏了分区容错性。
所以无论怎么实现,都只能尽量的满足CAP的三者,而无法保证三者同时绝对的满足。
CAP理论的舍弃方案 既然CAP无法三者共存,那么就需要对其中的1个进行舍弃掉。
舍弃C: 舍弃了一致性,也就是说允许同一时刻不同节点获取到的数据是不一样的,但是保证了高可用性,最典型的例子就是微信抢红包和12306系统,明明看到的红包是有的,打开就抢光了;明明看到还有票的,一点购买秒没了。这样的涉及虽然稍微牺牲了一点用户体验,但是对于系统做到了很好的保护,不会导致系统长期处于阻塞状态而慢慢瘫痪
舍弃A: 舍弃了可用性,也就是说允许用户操作失败,但是数据是绝对一致的,最典型的例子就是金融行业,在进行转账或提现的时候往往都不会立马告诉你操作成功,而是提示操作正在进行中,快的几分钟满的1-2个工作日才能正常到账,虽然舍弃了可用性,但是可以保证的是数据的绝对一致性,不可能会出现这里看到的余额是100,那里看到的余额是200的情况。
舍弃P: 舍弃了分区容错性,也就是说一个节点宕机了,整个系统就不可用了,但是可以保持一致性和可用性。不过对于分布式系统来说,如果舍弃了P,就会使得分布式系统黯然失色,因为分布式系统的两大优势就是分担压力和容错性高。
所以一般而言P是不可舍弃的,而需要舍弃的就是C和P,这个就需要针对系统的特点来选取方案,对于对数据很敏感的金融行业就必须保持数据的一致性,此时就需要舍弃A;而对于高并发下不能容忍用户操作频繁失败的情况,就需要舍弃一定的一致性,而保证可用性。比如一些新闻、微博类的展示类系统,对于数据一致性没有太高的要求,就可以优先保证可用性。