CAP - 分布式系统

2/20/2021 CAPACID

# CAP - 分布式系统

# 分布式系统出现的原因

我们讨论一个事物的出现的原因,最好的办法就是看没有这个事物之前是怎么样的。

在没有分布式系统之前,我们的系统软件都是单点的

单点系统有以下不足

  • 单点系统在高并发下的可用性不足,会有系统瓶颈
  • 单点故障(SPOF),无法做到高可用

以此类推: 我们的系统

  • 需要保障高并发下的服务可用性
  • 需要保障部分服务故障的可用性

所以分布式系统的核心诉求就是可用性

分布式系统两大初衷

  • 横向扩展(scalability) 解决单点故障
  • 高可用性(availability) 解决部分服务故障

# CAP定理出现的原因

在明天CAP定理前,业界没有明确的标准设计和实施分布式系统,一个分布式系统由多个模块组成,模块可能由不同的开发人员完成,然而在公共层,没有明确的指导去怎么完成。

比如:两个节点的数据,如果发生储物哦,到底该怎么做,如果没有统一的标准和方向,那么很可能在一个分布式系统中,会出现不同的处理情况

# CAP定理背景

CAP 定理(CAP theorem)又被称作布鲁尔定理(Brewer's theorem),是加州大学伯克利分校的计算机科学家埃里克·布鲁尔(Eric Brewer)在 2000 年的 ACM PODC 上提出的一个猜想。 2002 年,麻省理工学院的赛斯·吉尔伯特(Seth Gilbert)和南希·林奇(Nancy Lynch)发表了布鲁尔猜想的证明,使之成为分布式计算领域公认的一个定理。对于设计分布式系统的架构师来说,CAP 是必须掌握的理论。

需要注意的是CAP有两版

  • 第一版简单翻译

对于一个分布式计算系统,不可能同时满足一致性(Consistence)、可用性(Availability)、分区容错性(Partition Tolerance)三个设计约束。

  • 第二版翻译

在一个分布式系统(指互相连接并共享数据的节点的集合)中,当涉及读写操作时,只能保证一致性(Consistence)、可用性(Availability)、分区容错性(Partition Tolerance)三者中的两个,另外一个必须被牺牲。

  • 两版比较

第二版强调了CAP理论的场景,强调了interconnectedshare data,为何强调这两点,因为分布式系统不一定会互联和共享数据。 最简单的例如 Memcache 的集群,相互之间就没有连接和共享数据,因此 Memcache 集群这类分布式系统就不符合 CAP 理论探讨的对象; 而 MySQL 集群就是互联和进行数据复制的,因此是 CAP 理论探讨的对象。

第二版强调了write/read pair,这点其实是和上一个差异点一脉相承的。 也就是说,CAP 关注的是对数据的读写操作,而不是分布式系统的所有功能。 例如,分布式的选举机制就不是 CAP 探讨的对象。

现在大部分人讨论CAP都是按照第一版的解释来的,但是忽略了使用场景

基于第二版的重新概述

一致性(Consistency)

  • 第一版解释:所有节点在同一时刻都能看到相同的数据。
  • 第二版解释:对某个指定的客户端来说,读操作保证能够返回最新的写操作结果。

区别:

  • 第一版从节点node的角度描述,第二版从客户端client的角度描述。
  • 第一版强调同一时刻拥有相同数据(same time + same data),第二版并没有强调这点。
  • 意味着实际上对于节点来说,可能同一时刻拥有不同数据(same time + different data),这和我们通常理解的一致性是有差异的,为何做这样的改动呢?
  • 对于系统执行事务来说,在事务执行过程中,系统其实处于一个不一致的状态,不同的节点的数据并不完全一致, 因此第一版的解释“All nodes see the same data at the same time”是不严谨的。 而第二版强调 client 读操作能够获取最新的写结果就没有问题,因为事务在执行过程中,client 是无法读取到未提交的数据的, 只有等到事务提交后,client 才能读取到事务写入的数据,而如果事务失败则会进行回滚,client 也不会读取到事务中间写入的数据。

可用性(Availability)

  • 第一版解释:每个请求都能得到成功或者失败的响应。
  • 第二版解释:非故障的节点在合理的时间内返回合理的响应(不是错误和超时的响应)。 区别:

第一版的 每个请求 是不严谨的,因为只有非故障节点才能满足可用性要求,如果节点本身就故障了,发给节点的请求不一定能得到一个响应。

第一版的 成功或则失败 的定义太泛了,几乎任何情况,无论是否符合 CAP 理论,我们都可以说请求成功和失败, 因为超时也算失败、错误也算失败、异常也算失败、结果不正确也算失败;即使是成功的响应,也不一定是正确的。 例如,本来应该返回 100,但实际上返回了 90,这就是成功的响应,但并没有得到正确的结果。 相比之下,第二版的解释明确了不能超时、不能出错,结果是合理的,注意没有说“正确”的结果。 例如,应该返回 100 但实际上返回了 90,肯定是不正确的结果,但可以是一个合理的结果。

分区容忍性(Partition Tolerance)

  • 第一版解释:出现消息丢失或者分区错误时系统能够继续运行。
  • 第二版解释:当出现网络分区后,系统能够继续“履行职责”。 区别:和上面一样,第二版在解释上更加严谨和准确

# CAP的应用

CAP理论三要素当中只能满足两个,但放到分布式环境下,我们必须要选择P(分区容忍), 因为网络本身无法做到 100% 可靠,有可能出故障,所以分区是一个必然的现象。 如果我们选择了 CA 而放弃了 P,那么当发生分区现象时,为了保证 C,系统需要禁止写入,当有写入请求时, 系统返回 error(例如,当前系统不允许写入),这又和 A 冲突了,因为 A 要求返回 no error 和 no timeout。 因此,分布式系统理论上不可能选择 CA 架构,只能选择 CP 或者 AP 架构。

# 1.CP

cp

如图所示。为了保证一致性,当发生分区现象后,Y数据已经更新到A节点,但由于A和B之间的复制中断,数据Y无法同步到B节点, 当客户端访问B节点的时候,B节点需要返回ERROR,这种处理违背了可用性的要求,因此CAP三者只能满足CP

# 2.AP

ap

如图所示,为了保证可用性,当数据Y更新到A节点后,由于A和B之间的复制通道终端,数据Y无法同步到B节点,这时客户端C访问B节点时, B节点将数据X返回给客户端,而实际上最新的数据是Y,这就违背一致性,因此 CAP 三者只能满足 AP。

注意:这里 B 节点返回 X,虽然不是一个“正确”的结果,但是一个“合理”的结果,因为 X 是旧的数据,并不是一个错乱的值, 只是不是最新的数据而已。

# CAP常见问题

1.CAP的粒度是整个系统,这个系统要么是CP要么是AP。

CAP关注的粒度重来都不是整个系统,而应该是数据, 以财务系统距离,账户余额和财务流水都必须要一致性,这时候我们要考虑的是一致性, 但是会员的资料没有很强的一致性要求。所以在一个系统当中会根据不同的数据需要有不同的选择

2.CAP理论忽略了网络延迟 分布式系统中,节点之间的数据同步是基于网络,有网络就会有延迟,这意味着CAP当中的C在实践中不可能完美实现, 不同业务系统对上诉耗时的敏感度不同,当发生网络分区时,系统中多个节点的数据一定是不一致的,但是可以选择对用户表现出一致性, 代价是牺牲可用性,将未能同步得到最新数据的部分节点,设置为不可用状态,而对用户是无感知的,当然我们也可以选择AP, 只是会返回数据的不一致。所以CAP当中的C是对于用户表现出的一致性

3.CAP在没有p的正常情况下,是可以满足CA的 CAP 理论告诉我们分布式系统只能选择 CP 或者 AP, 但其实这里的前提是系统发生了“分区”现象。如果系统没有发生分区现象,也就是说 P 不存在的时候(节点间的网络连接一切正常), 我们没有必要放弃 C 或者 A,应该 C 和 A 都可以保证,这就要求架构设计的时候既要考虑分区发生时选择 CP 还是 AP, 也要考虑分区没有发生时如何保证 CA。

4.牺牲不代表不补偿 CAP 理论告诉我们三者只能取两个,需要“牺牲”(sacrificed)另外一个,这里的“牺牲”是有一定误导作用的, 因为“牺牲”让很多人理解成什么都不做。实际上,CAP 理论的“牺牲”只是说在分区过程中我们无法保证 C 或者 A,但并不意味着什么都不做。 因为在系统整个运行周期中,大部分时间都是正常的,发生分区现象的时间并不长。 例如,99.99% 可用性(俗称 4 个 9)的系统,一年运行下来,不可用的时间只有 50 分钟;99.999%(俗称 5 个 9)可用性的系统, 一年运行下来,不可用的时间只有 5 分钟。分区期间放弃 C 或者 A,并不意味着永远放弃 C 和 A,我们可以在分区期间进行一些操作, 从而让分区故障解决后,系统能够重新达到 CA 的状态。

最典型的就是在分区期间记录一些日志,当分区故障解决后,系统根据日志进行数据恢复,使得重新达到 CA 状态。 以用户管理系统为例,对于用户账号数据,假设我们选择了 CP,则分区发生后,节点 1 可以继续注册新用户, 节点 2 无法注册新用户(这里就是不符合 A 的原因,因为节点 2 收到注册请求后会返回 error), 此时节点 1 可以将新注册但未同步到节点 2 的用户记录到日志中。当分区恢复后,节点 1 读取日志中的记录,同步给节点 2, 当同步完成后,节点 1 和节点 2 就达到了同时满足 CA 的状态。

而对于用户信息数据,假设我们选择了 AP,则分区发生后,节点 1 和节点 2 都可以修改用户信息,但两边可能修改不一样。 例如,用户在节点 1 中将爱好改为“旅游、美食、跑步”,然后用户在节点 2 中将爱好改为“美食、游戏”, 节点 1 和节点 2 都记录了未同步的爱好数据,当分区恢复后,系统按照某个规则来合并数据。 例如,按照“最后修改优先规则”将用户爱好修改为“美食、游戏”,按照“字数最多优先规则”则将用户爱好修改为“旅游,美食、跑步”, 也可以完全将数据冲突报告出来,由人工来选择具体应该采用哪一条。

# ACID

ACID 是数据库管理系统为了保证事务的正确性而提出来的一个理论,ACID 包含四个约束,下面我来解释一下。

  • 1.Atomicity(原子性)

一个事务中的所有操作,要么全部完成,要么全部不完成,不会在中间某个环节结束。 事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。

  • 2.Consistency(一致性)

在事务开始之前和事务结束以后,数据库的完整性没有被破坏。

  • 3.Isolation(隔离性)

数据库允许多个并发事务同时对数据进行读写和修改的能力。隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。 事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)

  • 4.Durability(持久性)

事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

可以看到,ACID 中的 A(Atomicity)和 CAP 中的 A(Availability)意义完全不同, 而 ACID 中的 C 和 CAP 中的 C 名称虽然都是一致性,但含义也完全不一样。ACID 中的 C 是指数据库的数据完整性, 而 CAP 中的 C 是指分布式节点中的数据一致性。再结合 ACID 的应用场景是数据库事务, CAP 关注的是分布式系统数据读写这个差异点来看,其实没有太多可比性。

# BASE

BASE 是指基本可用(Basically Available)、软状态( Soft State)、最终一致性( Eventual Consistency), 核心思想是即使无法做到强一致性(CAP 的一致性就是强一致性),但应用可以采用适合的方式达到最终一致性。

  • 基本可用(Basically Available) 分布式系统在出现故障时,允许损失部分可用性,即保证核心可用。

这里的关键词是“部分”和“核心”,具体选择哪些作为可以损失的业务,哪些是必须保证的业务,是一项有挑战的工作。 例如,对于一个用户管理系统来说,“登录”是核心功能,而“注册”可以算作非核心功能。 因为未注册的用户本来就还没有使用系统的业务,注册不了最多就是流失一部分用户,而且这部分用户数量较少。 如果用户已经注册但无法登录,那就意味用户无法使用系统。例如,充了钱的游戏不能玩了、云存储不能用了……这些会对用户造成较大损失, 而且登录用户数量远远大于新注册用户,影响范围更大。

  • 软状态(Soft State) 允许系统存在中间状态,而该中间状态不会影响系统整体可用性。这里的中间状态就是 CAP 理论中的数据不一致。

  • 最终一致性(Eventual Consistency) 系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。

这里的关键词是“一定时间” 和 “最终”,“一定时间”和数据的特性是强关联的,不同的数据能够容忍的不一致时间是不同的。 举一个微博系统的例子,用户账号数据最好能在 1 分钟内就达到一致状态,因为用户在 A 节点注册或者登录后, 1 分钟内不太可能立刻切换到另外一个节点,但 10 分钟后可能就重新登录到另外一个节点了;而用户发布的最新微博, 可以容忍 30 分钟内达到一致状态,因为对于用户来说,看不到某个明星发布的最新微博,用户是无感知的,会认为明星没有发布微博。 “最终”的含义就是不管多长时间,最终还是要达到一致性的状态。

BASE 理论本质上是对 CAP 的延伸和补充,更具体地说,是对 CAP 中 AP 方案的一个补充。前面在剖析 CAP 理论时, 提到了其实和 BASE 相关的两点:

  • CAP 理论是忽略延时的,而实际应用中延时是无法避免的。 这一点就意味着完美的 CP 场景是不存在的,即使是几毫秒的数据复制延迟, 在这几毫秒时间间隔内,系统是不符合 CP 要求的。因此 CAP 中的 CP 方案,实际上也是实现了最终一致性,只是“一定时间”是指几毫秒而已。

  • AP 方案中牺牲一致性只是指分区期间,而不是永远放弃一致性。 这一点其实就是 BASE 理论延伸的地方,分区期间牺牲一致性, 但分区故障恢复后,系统应该达到最终一致性。

综合上面的分析,ACID 是数据库事务完整性的理论,CAP 是分布式系统设计理论,BASE 是 CAP 理论中 AP 方案的延伸。

# 总结

CAP在没有p的情况下,系统就是CA,在出现p的情况下,要根据数据情况下考虑保障C还是保障A CAP需要在互联和数据共享的前提下讨论

# 思考

12306系统按照CAP理论,哪些属于CP,那些属于AP 电商网站核心模块 会员,订单,商品,支付,促销,在CAP理论当中,哪些属于CP,那些属于AP

Mr.s Luo

# 资料


收录时间: 2021-02-20

最后更新时间: 10/11/2021, 3:33:08 PM