分布式系统CAP定理教程

本文探讨了 CAP 定理。理解 CAP 对于设计分布式系统至关重要,我们将深入研究每个属性的含义。

什么是分布式系统?
分布式系统将计算和数据分布在网络内的多个互连节点上。这可能涉及卸载处理能力或在地理上分散数据以加快交付速度。与将数据存储在单个位置的集中式系统不同,分布式系统将数据分布在多个互连点上。

分布式系统的问题挑战:
1、分区:
第一个问题是网络故障:网络链接可能会中断,从而产生网络分区,从而使整个网络被分成孤立的组。每个分区都失去了与其他分区的通信。系统承受此类分区的能力称为分区容错性。需要注意的是,实现 100% 分区容错实际上是不可能的;所有分布式系统在某些时候都容易受到网络分区的影响。

这些分区虽然是暂时的,但会破坏系统各部分之间的通信。让我们考虑一下 Instagram 或 Facebook 等社交媒体平台。如果发生分区,则在网络恢复之前,其他分区中的用户可能无法看到新发布的照片​​。

2、一致性:
这引出了分布式系统的另一个重要属性。 “一致性”。您已经注意到,如果发生两个分区,则两个分区看到的数据是不同的(或者换句话说,不一致)。一致性是衡量给定时间网络上的系统数据是否正确的指标。

一致性在金融应用中起着至关重要的作用。与社交媒体帖子不同,数据在整个系统中保持一致的速度是衡量系统一致性的指标。否则,这可能会导致严重的问题,例如双重支出问题。

假设 Alice 的账户中有 100 美元,所有服务器都与 Alice 的账户余额 100 美元一致。Alice 从服务器 A 处在线购买了价值 90 美元的手表。服务器 A 完成交易并向其他服务器发送通知,要求扣除 Alice 账户中的 90 美元。但在信息传播之前,突然发生了分区,服务器 B 没有收到 Alice 的交易。如果爱丽丝呼叫服务器 B 并再次进行交易,服务器仍然认为爱丽丝有 100 美元,并让她再次消费。如果爱丽丝用 50 美元从服务器 B 处买了一个包,交易仍然通过。
(这个案例其实是一个业务场景,技术试图用一种通用方式解决业务。)

可以看出,在这种金融系统中,一致性是一个大问题,它应该具有更高的一致性。与社交媒体平台相比,你以多快的速度收到朋友的更新并不重要。现在,我们知道金融交易系统需要更高的一致性。但我们该如何实现呢?

一致性级别可以有很多种,但让我们来分析一下主要用于分布式系统的以下级别:

  • 线性化
  • 顺序一致性
  • 因果一致性
  • 最终一致性

线性化Linearizability
线性化是最高的一致性级别。这种一致性算法的工作原理是,如果有任何节点数据需要更新,就为系统中的所有节点添加一个读取锁。通过为所有节点添加读锁,我们可以确保系统中的任何节点都不会读取部分更新的数据。一旦所有数据处于一致状态,读锁就会被移除。如果存在网络分区,系统需要更多时间才能达到一致状态。如果客户端连接到一个节点,并在该节点被锁定时请求读取数据,会发生什么情况呢?客户端必须等待节点释放锁。

这就引出了第三个重要属性--可用性。可用性是指当客户端向节点提出请求时,节点会做出响应的属性。如果节点没有准备好为请求提供服务,客户端将得不到响应或响应失败。在线性化示例中,我们锁定了节点,这样客户端就得不到响应。这意味着,在数据变得一致之前,节点是不可用的。我们可以得出这样的结论:如果一致性越高,我们就无法实现更高的可用性。

顺序一致性
与线性化相比,顺序一致性是一种宽松的一致性模型。顺序一致性不是为所有数据更新锁定所有节点,而是按时间顺序锁定节点。想想聊天应用程序。当两个人聊天时,两个人的信息都应该按照正确的时间顺序排列。否则,理解起来就会一团糟。让我们通过一个例子来理解。

Alice 需要向聊天群组发送一条信息,她向系统发送了这条信息。假设系统没有分区,她的信息会传播到所有节点。现在,Bob 也需要向群组发送一条信息,但由于发生了网络分区,一些节点没有更新 Bob 的信息。现在,如果爱丽丝在这个分区系统中发送另一条信息,一些节点仍然不会更新鲍勃的信息。如果节点不更新鲍勃的信息,只添加爱丽丝的信息,聊天就会变得一团糟。在这种情况下,顺序一致系统会在节点上加一个写锁,只有在所有之前发布的数据都已添加的情况下,系统才能写入节点。在节点更新以前的数据之前,它必须等待以前发送的信息到达节点。

在这种一致性模式下,我们只考虑每个节点数据的顺序一致性。与线性化模式相比,在线性化模式中,写锁会一直应用到事件的顺序解决为止,而在这种模式中,节点是可用的。客户端仍然可以从分区系统中的给定节点获得响应,但最多只能获得顺序正确的最后一个数据。

因果一致性
因果一致性是一种更为宽松的一致性模型,它不考虑顺序。因果一致性只考虑数据之间的关系。例如,想想一个社交媒体平台,你可以在上面发布图片和评论。爱丽丝在平台上发布了一张照片,与此同时,鲍勃也在平台上发布了一张照片。这两个帖子没有任何关系。发布的先后顺序不会影响第三人查理查看这两张照片。但是,每张照片都有一个评论区。当查理看到照片上的评论时,这些评论应按时间顺序排列,以便他理解。这个系统中的评论是因果一致的。这意味着,在某些情况下,顺序确实很重要,但并非在所有情况下都如此。如果存在不相关的实体(如帖子),则一致性更宽松,而评论则依赖于相关的帖子。

最终一致性
现在,我们可以轻松理解 "最终一致性 "了。想想看,同样是一个没有评论功能的社交媒体平台。现在,爱丽丝和鲍勃发布了照片,查理可以在自己的 feed 上看到他们发布的照片。他收到数据的顺序并不重要。

这让我们想到关于可用性的另一个重要事实。在线性化一致性级别中,由于锁定,我们无法实现更高的可用性。但在最终一致性中,我们不需要任何锁。因此,服务器节点在任何时候都是可用的。

什么是 CAP 定理?
现在,我们发现了 CAP 定理的全部内容,是时候完成拼图了。我们已经讨论了分布式系统的三个特性。分区容忍性(Partition Tolerance)告诉我们系统可以容忍分区;一致性(Consistency)确保数据在分布式系统中保持一致;可用性(Availability)确保系统始终响应客户请求。CAP 定理指出,我们只能从三个属性中选择两个。让我们来看看这三种情况。

1、选择分区容错性和一致性而非可用性
在这种情况下,我们允许系统有分区。但我们需要保持系统的一致性。我们讨论过的金融交易场景就属于这种情况。为了保持一致性,我们必须锁定节点,直到数据在系统中变得一致。只有这样,才允许从系统中读取数据。因此,可用性是有限的。

2、选择分区容忍度和可用性而非一致性
在这种情况下,我们不需要系统具有严格的一致性。回顾一下最终一致性中讨论的社交媒体系统。我们不需要一致的数据,而是需要数据以任何顺序排列。有了宽松的一致性级别,我们就不需要锁定节点,而且节点总是可用的。

3、分区容差下的可用性和一致性
这种系统更像是集中式系统,而不是分布式系统。如果没有网络分区,我们就无法构建系统。如果我们同时确保可用性和一致性,那么就不可能存在任何分区。也就是说,这是一个集中式系统。因此,我们不讨论分布式系统中的可用性和一致性系统。

CAP 定理用例
现在你知道什么是 CAP 定理了吧。让我们来看看上述三种情况下使用的一些工具示例。

1、分区容忍和一致性系统
Redis 和 MongoDB 是针对 CP(一致和分区容忍系统)的流行数据库解决方案。这些数据库可作为分布式数据库运行,并允许存在分区。即使存在分区,也能让您在连接的所有数据库中获得一致的数据。

2、分区容忍度和可用系统
该系统不太关心系统的一致性。它关心的是响应速度和运行速度。这包括 Cassandra 和 CouchDB 等数据库。这些数据库专为在分布式环境中运行和加快运行速度而构建。

3、一致可用的系统
这类系统不是分布式系统,而是集中式系统。SQLite 和 H2 等数据库可在单个节点上运行。这些数据库无需锁定节点,而且是唯一的节点,因此始终保持一致性和可用性。但在分布式系统上却不能使用,因为它不能容忍分区。


为什么 MYSQL 没有被列入其中?
一般认为,MySQL 是一种 CA 系统,旨在提供良好的一致性和可用性,同时牺牲分区容错性。原因在于 MYSQL 以主-从模式运行,其中主节点是客户端要访问的节点。因此,我们所说的并不是真正的分布式系统。但通过不同的配置,你仍然可以把它当作一个 CP 系统来使用。

如你所见,CAP 定理对分布式系统施加了限制。作为系统设计者和开发者,我们必须选择优先考虑的属性:一致性、可用性或分区容忍性。所选择的一致性模型将决定我们是优先考虑高可用性,还是牺牲一些可用性来确保一致性。有许多工具可以帮助你根据这些权衡来设计应用程序。明智选择!下次遇到分布式系统时,请考虑这三个关键特性。