0%

CAP理论与BASE理论

问题

分布式系统应用广泛起来,大型网站多是分布式。但分布式系统的难点之一是各个节点的状态如何保持一致。

处理数据一致性问题考虑的理论是CAP理论

BASE定理来源是CAP中一致性和可用性的权衡结果,来自大规模互联网分布式系统的总结。
核心思想是即使无法做到强一致性,但是每个应用可以根据自身的业务特定,采用合适的方式来达到最终一致性。

CAP理论

定义

CAP名称对应分布式系统的单个指标:

C consistency 一致性:所有节点访问同一份最新的数据副本,强调数据是正确的

Consistency: Every read receives the most recent write or an error.

A availability 可用性:客户端的任何请求都能得到响应,不会返回响应错误,但不保证数据是最新的,强调不出错

Availability: Every request receives a (non-error) response - without the guarantee that it contains the most recent write.

P partition tolerance 分区容忍性:当任意数量的消息丢失或延迟到达时系统仍会继续提供服务,强调系统不停止服务

Partition tolerance: The system continus to operate despite an arbitrary number of messages being dropped (or delayed) by the network between nodes.

CAP理论的内容:一个分布式系统不能同时满足C,A,P。经典的图述如下:

image-20230707194212957

(CA即是单机模式)

举例理解C和A

如图所示一个简单的分布式系统:

分布式系统示意图

满足一致性C,即两台服务器种的数据是一样的,数据库1的内容和数据库2的一致。

满足可用性A,即当客户端有请求时,不管是请求哪一台服务器,客户端都会得到立即响应。

注意:CAP理论的C != 事务ACID特性的C

CAP三者的冲突

image-20230708095259849

假设分布式系统的服务间之间的网络断开了,但仍要满足分区容错性(即保证系统还能用)。

如果用户向服务器1发送更新数据的请求,此时数据库1里的数据将被更新,假设更新前数据库1和数据库2的数据时一致的,都是data0,更新的数据为data0,那么更新完的情况为

image-20230708095836568

若有用户向服务器2发送数据请求,由于网络故障数据库数据未同步,数据库2无法为用户反馈最新的数据data1,有两种选择:

  • 保证可用性,响应旧的数据data0给用户
  • 保证一致性,阻塞等待,直到数据更新操作完成后在给用户响应

用CAP理论分析分布式系统

对于一个分布式系统而言,网络分区故障常常是不可避免的,所以P是前提必须保证,因为只要有网络交互就一定会有延迟和数据丢失,这种状况我们必须接受,必须保证系统不能挂掉。所以只剩下C、A可以选择。要么保证数据一致性(保证数据绝对正确),要么保证可用性(保证系统不出错)。

当选择了C(一致性)时,如果由于网络分区而无法保证特定信息是最新的,则系统将返回错误或超时。

当选择了A(可用性)时,系统将始终处理客户端的查询并尝试返回最新的可用的信息版本,即使由于网络分区而无法保证其是最新的。

  • 对于NoSQL数据库,更注重可用性——AP
  • 对于分布式关系型数据库系统,更注重一致性——CP。但常常分布式关系型数据库有着高可用性的需求,一般具备五个9(99.999%)以上的高可用性→CP+HA,产生了两个广泛应用的指标
    • RPO(Recovery Point Objective):恢复点目标,指数据库在灾难发生后会丢失多长时间的数据。分布式关系型数据库RPO=0。
    • RTO(Recovery Time objective):恢复时间目标,指数据库在灾难发生后到整个系统恢复正常所需要的时间。分布式关系型数据库RTO<几分钟。

BASE定理

定义

BASE即Basically Available(基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)

Basically Available:完全可用和完全不可用的折中,折中下可通过延迟响应、流量削峰等手段保障系统核心功能正常

Soft state:可变动的状态,强调的是数据状态处于一种临界状态(在确定与不确定之间?),一种短暂的临时状态?在最终一致性的系统中,读出来的数据不一定是最新的。

Eventually consistent:最终一致性的系统不承诺写入数据成功后,能立即从系统中读出最新的数据,也不承诺具体多久之后可以读到最新的数据,而是尽可能保障特定时间级别之后的数据可用

确保基本可用的措施

一个正常的系统,不可用的情况,除了网络和硬件的原因外,多半是由于过载引起的。 过载的流量可能是短暂的,如果我们不加以控制,就可能会压垮系统,就要求我们要对流量进行控制来保障系统的可用性。

  • 削峰填谷

如果流量的数据我们可以控制,比如我们在做个抢购,不同的商品我们可以错开抢购时间减少系统的压力;这样就避免了大量的流量突发到系统中,从而压垮系统;

如果我们无法控制流量,那我们可以将数据保存到队列中的方式。我们系统可以根据自己处理能力,来消费队列数据,从而达到削峰填谷的目的。

  • 延迟响应

刚才的削峰填谷利用到了队列,对用户的请求不直接处理,而是缓存起来,慢慢处理,处理完毕后再返回,这对用户来说响应被延迟了,但是系统却可以处理更多的用户请求,这也是保证系统基本可用的一种手段。

  • 服务降级

服务降级体现了基本可用的基本所在,在超系统负载的大流量过来之后,我们牺牲系统非必要的功能,比如降低日志级别,比如显示分辨率更低的图片等手段,来降低系统的资源消耗,保证核心能力的正常运行,这也是保证系统基本可用手段。

  • 过载保护

如果以上手段,还是无法应对现在的流量,只能进入过载保护截断了,系统根据自己的能力抛弃超时的请求,或者随机抛弃一些请求,直接返回错误。这是比较狠的,比较粗暴直接的手段来保证系统的可用。

确保最终一致性的措施

存在最终一致性的系统,显然是存在多个副本的,通过多个副本来保证系统的可用性。在网络中不同的节点存在同一个副本,那就会存在副本数据的不一致问题,因为网络复制必然会存在延迟,当然我们可以等所有的副本数据都同步完成后再进行返回给客户端,但是那样系统的性能必然比较低,而且一旦一个副本所在的节点断开了,系统就无法响应了,可用性都难以保证了。

所以在一致性要求不严格的情况下,我们多采用最终一致性,那最终又是通过上面手段来保证的那,是如果修复不同的副本数据那。

  • 写时修复

其实这是能想到的最直接的方式,在多个副本写的时候,如果其中一个写失败了,就缓存起来,系统自动通过重试的手段进行修复。 在我看来,写时修复,更快达到最终一致性,因为修复动作离写操作最近。 而且写时修复不需要进行数据对比,所以性能最好。

  • 读时修复

我们在写数据的时候不关心失败还是成功,只是在读数据的时候,我们可以同时读多个节点的同一份数据,然后根据一定的规则,比如以超过半数的数据值为准的办法,来决定返回的值,如果我们写的时候也按照一定规则的话(比如写要超过半数的节点),我们就可以任务这个数据值是正确的,以这个值为准修复刚才不是这个值的节点。 比如 Cassandra 的 Read Repair 模式下,读时候发现数据不一致的时候会自动修复。

  • 异步修复

通过定时不同节点比对的方式,来对照数据是否需要修复,如果需要修复,则进行同步。 这种修复方式,由于涉及到数据的比对,所以性能不是很好。(?为什么这里的异步效果会差)

应用场景

Base理论的主要思想就是竭尽全力的保证系统可用性,期间允许数据副本之间出现数据不一致的情况,只要最终能达到数据一致性就好。所以很明显,如果产品追求的是可用性,那么base理论就很合适,但是如果是金融项目,涉及到钱这一块,那么强一致性才是重中之重。

参考资料

轻松理解CAP理论 - 知乎 (zhihu.com)

10分钟搞懂CAP理论

分布式基础-BASE理论 - 知乎 (zhihu.com)