重新思考 CAP 定理

CAP Theorem: Revisited 译文

记录:两个月之前,我写了一篇博客来解释 CAP 定理。发表之后我意识到,我在这个主题上的思考已经非常过时,并且不适应于真实世界。我尝试在这篇博客上弥补该缺陷。

在当今的技术环境中,当需要额外的资源(计算,存储等)以在合理的时间范围内成功完成工作负载时,我们见证了对系统进行扩展的强烈且不断增长的需求。这可以通过向系统添加其他商品硬件来处理增加的负载来实现。 这种扩展策略的结果是系统增加了额外的复杂度。 这就是 CAP 定理起作用的地方。

CAP 定理指出,在一个分布式系统(指互相连接并共享数据的节点的集合)中,当涉及读写操作时,只能保证一致性(Consistence)、可用性(Availability)、分区容错性(Partition Tolerance)三者中的两个,另外一个必须被牺牲。 但是,正如下面看到的那样,这里没有太多选择。 image

一致性 - 对某个指定的客户端来说,读操作保证能够返回最新的写操作结果。

可用性 - 非故障的节点在合理的时间内返回合理的响应(不是错误和超时的响应)。

分区容错性 - 当出现网络分区后,系统能够继续“履行职责”。

在继续讲解之前,我们先纠正一个概念:
面向对象编程 != 网络编程!

在构建共享内存的应用程序时,一旦节点在空间和时间上分开,有一些我们认为理所当然的假设就会崩溃。

分布式计算的谬误之一是网络是可靠的。 但它们不是。 网络和网络的某些部分经常会意外崩溃。 网络故障发生在您的系统上,您无法选择何时发生。

鉴于网络并不完全可靠,您必须容忍分布式系统中的分区。 不过,幸运的是,您可以选择在发生分区时要做什么。 根据 CAP 定理,这意味着我们有两个选择:一致性和可用性。

CP-Consistency/Partition Tolerance-等待分区节点的响应,这可能导致超时错误。 系统还可以根据您想要的情况选择返回错误。 当您的业务需求要求原子读写时,请选择“可用性之上的一致性”。

如下图所示,为了保证一致性,当发生分区现象后,N1 节点上的数据已经更新到 y,但由于 N1 和 N2 之间的复制通道中断,数据 y 无法同步到 N2,N2 节点上的数据还是 x。这时客户端 C 访问 N2 时,N2 需要返回 Error,提示客户端 C“系统现在发生了错误”,这种处理方式违背了可用性(Availability)的要求,因此 CAP 三者只能满足 CP。

image

AP-Availability/Partition Tolerance-返回拥有数据的最新版本,这可能是过时的。 此系统状态还将接受在分区解析后可以稍后处理的写操作。 当您的业务需求允许系统中的数据同步时具有一定的灵活性时,请选择“可用性高于一致性”。 当系统尽管存在外部错误(购物车等)而仍需要继续运行时,可用性也是一个令人信服的选择.

如下图所示,为了保证可用性,当发生分区现象后,N1 节点上的数据已经更新到 y,但由于 N1 和 N2 之间的复制通道中断,数据 y 无法同步到 N2,N2 节点上的数据还是 x。这时客户端 C 访问 N2 时,N2 将当前自己拥有的数据 x 返回给客户端 C 了,而实际上当前最新的数据已经是 y 了,这就不满足一致性(Consistency)的要求了,因此 CAP 三者只能满足 AP。注意:这里 N2 节点返回 x,虽然不是一个“正确”的结果,但是一个“合理”的结果,因为 x 是旧的数据,并不是一个错乱的值,只是不是最新的数据而已。

image

一致性和可用性之间的决定是软件的权衡。 您可以选择面对网络分区时要做什么-控制权就在您手中。 网络中断(无论是永久性的还是永久性的)都是生活中不可或缺的事实,无论您是否希望发生,都会发生-这是软件外部存在的情况。

构建分布式系统具有许多优点,但同时也增加了复杂性。 了解面对网络错误时可以使用的折衷方法,并选择正确的路径对于应用程序的成功至关重要。 从一开始就无法正确执行此操作,可能会在首次部署之前使您的应用程序注定要失败。

原文:
CAP Theorem: Revisited

Published: January 11 2021

blog comments powered by Disqus