CAP 理论

CAP 理论概念

CAP 理论指的就是,在分布式系统中 C、A、P 这三个特征不能同时满足,只能满足其中两个。

  • Consistent:所有节点访问同一份最新的数据副本;
  • Availability:多个节点上的服务能及时响应;
  • Partition Tolerance:分区容错性,是指在分布式系统遇到网络分区的情况下,仍然可以响应用户的请求。多个节点之间即使出现网络故障,也不会影响各自节点响应请求。一般情况下通过多副本的形式来解决这个问题。

网络分区:在实际场景中,网络环境不可能百分之百不出故障,比如网络拥塞、网卡故障等,会导致网络故障或不通,从而导致节点之间无法通信,或者集群中节点被划分为多个分区,分区中的节点之间可通信,分区间不可通信。这种由网络故障导致的集群分区情况,通常被称为“网络分区”。

CP vs AP 架构

在分布式系统中,网络分区不可避免,因此分区容错性 P 必须满足。接下来,我们就来讨论一下在满足分区容错性 P 的情况下,一致性 C 和可用性 A 是否可以同时满足。

  • 第一种处理方式是,保证一致性 C,牺牲可用性 A。比如,金融场景,哪怕响应慢一点,也要保证金钱不会出错。比如,电缆被挖了,选择直接不提供服务了。
  • 第二种处理方式是,保证可用性 A,牺牲一致性 C。不追求实时一致场景下,采用最终一致性。

什么时候放弃 P?放弃 P 的情况下,节点之间不需要传输数据,相当于是单点服务。例如只放在一台机器上的数据库服务,例如一个简单计算器加减乘除服务。

实际应用架构

ZooKeeper、HBase 就是 CP 架构,Cassandra、Eureka 就是 AP 架构,Nacos 不仅支持 CP 架构也支持 AP 架构。

  1. ZooKeeper 保证的是 CP。 任何时刻对 ZooKeeper 的读请求都能得到一致性的结果,但是, ZooKeeper 不保证每次请求的可用性比如在 Leader 选举过程中或者半数以上的机器不可用的时候服务就是不可用的。
  2. Eureka 保证的则是 AP。 Eureka 在设计的时候就是优先保证 A (可用性)。在 Eureka 中不存在什么 Leader 节点,每个节点都是一样的、平等的。因此 Eureka 不会像 ZooKeeper 那样出现选举过程中或者半数以上的机器不可用的时候服务就是不可用的情况。 Eureka 保证即使大部分节点挂掉也不会影响正常提供服务,只要有一个节点是可用的就行了。只不过这个节点上的数据可能并不是最新的。
  3. Nacos 不仅支持 CP 也支持 AP。

Redis 支持 AP 也支持 CP 场景。

Redis AP 场景?

  • 主从复制:在默认的异步复制模式下,当主节点接收到写请求后会立即响应客户端,而不等待从节点确认。这种情况下如果发生网络分区或主节点故障,可能会导致数据不一致。
  • Redis Sentinel:Sentinel 可以监控并自动故障转移主从结构的 Redis 实例。如果主节点不可用,它会选择一个从节点作为新的主节点。在这个过程中,可能由于异步复制的原因出现短暂的数据不一致。
  • Redis Cluster:Redis Cluster 提供了分区容错性和高可用性。每个分片都有多个副本,并且客户端可以读取任何副本。在网络分区的情况下,为了保证可用性,可能会牺牲一致性,即允许部分副本之间存在数据不一致。

Redis CP 场景?

  • 单实例模式:在单一 Redis 实例中,不存在网络分区问题,因此可以认为它是 CP 系统。所有的读写操作都在同一个实例上执行,确保了一致性。
  • 同步复制:如果配置 Redis 主从复制为同步模式(使用 min-slaves-to-writemin-slaves-max-lag 参数),则只有当指定数量的从节点确认收到数据后,主节点才会返回给客户端。这样即使在网络分区时也能保持一致性,但可能会降低系统的可用性。
  • Redis Cluster 配置要求多数节点确认:在 Redis Cluster 中,可以通过设置 cluster-require-full-consensus 或者使用 WAIT 命令来要求多数节点确认写操作,从而提高一致性保障,但这同样可能影响系统在某些情况下的可用性。

CAP 补充

  • CAP 关注的粒度是数据,而不是整个系统。
  • CAP 是忽略网络延迟的。不要小看了这几毫秒或者几十毫秒的不一致,对于某些严苛的业务场景,例如和金钱相关的用户余额,或者和抢购相关的商品库存,技术上是无法做到分布式场景下完美的一致性的。
  • 当没有分区发生的时候,要做到考虑 CA 架构。
  • 放弃并不等于什么都不做,需要为分区恢复后做准备。
    • 在分区期间记录一些日志,当分区故障解决后,系统根据日志进行数据恢复,使得重新达到 CA 状态。
    • 如果选择了 AP,可以在合并数据的时候,由人工来选择具体应该采用哪一条。
    • AP 方案中牺牲一致性只是指分区期间,而不是永远放弃一致性。这一点其实就是 BASE 理论延伸的地方,分区期间牺牲一致性,但分区故障恢复后,系统应该达到最终一致性。

推荐阅读

  1. CAP 定理简化 (英文,有趣的案例)
  2. 神一样的 CAP 理论被应用在何方 (中文,列举了很多实际的例子)
  3. 请停止呼叫数据库 CP 或 AP (英文,带给你不一样的思考)

BASE 理论

Base 理论概念

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

BASE 理论本质上是对 CAP 的延伸和补充,更具体地说,是对 CAP 中 AP 方案的一个补充。

如果系统没有发生“分区”的话,节点间的网络连接通信正常的话,也就不存在 P 了。这个时候,我们就可以同时保证 C 和 A 了。因此,如果系统发生“分区”,我们要考虑选择 CP 还是 AP。如果系统没有发生“分区”的话,我们要思考如何保证 CA 。

因此,AP 方案只是在系统发生分区的时候放弃一致性,而不是永远放弃一致性。在分区故障恢复后,系统应该达到最终一致性。这一点其实就是 BASE 理论延伸的地方。

Base 理论三要素

  • 基本可用
    • 分布式系统在出现故障时,允许损失部分可用性,即保证核心可用。
    • 具体表现为:响应时间上有损失,系统功能上有损失。
    • 在实际应用时,需要明确哪些是可以损失的,哪些是必须保证的。
      • 电商网站在双十一大促等访问压力较大的时候,关闭商品排行榜等次要功能的展示,从而保证商品交易主流程的可用性,这也是我们常说的服务降级;
      • 为了错开双十一高峰期,电商网站会将预售商品的支付时间延后十到二十分钟,这就是流量削峰
      • 在你抢购商品的时候,往往会在队列中等待处理,这也是常用的延迟队列
  • 软状态
    • 允许系统存在中间状态,而该中间状态不会影响系统整体可用性。这里的中间状态就是 CAP 理论中的数据不一致。
  • 最终一致性
    • 系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。
    • 实现最终一致性的具体方式是什么呢? 《分布式协议与算法实战》 中是这样介绍:
      • 读时修复: 在读取数据时,检测数据的不一致,进行修复。比如 Cassandra 的 Read Repair 实现,具体来说,在向 Cassandra 系统查询数据的时候,如果检测到不同节点的副本数据不一致,系统就自动修复数据。
      • 写时修复: 在写入数据,检测数据的不一致时,进行修复。比如 Cassandra 的 Hinted Handoff 实现。具体来说,Cassandra 集群的节点之间远程写数据的时候,如果写失败就将数据缓存下来,然后定时重传,修复数据的不一致性。
      • 异步修复: 这个是最常用的方式,通过定时对账检测副本数据的一致性,并修复。
      • 比较推荐 写时修复,这种方式对性能消耗比较低。

ACID 理论

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

参考