欢迎来到分布式系统系列。在本文中,我们将学习并理解什么是 CAP 定理。CAP 代表一致性、可用性和分区容错性。当我们谈论CAP定理时,我们主要谈论的是分布式系统。首先,让我们了解一下什么是分布式系统。分布式系统是由运行在单台或多台机器上的多个进程组成的系统。在本次讲座中,我们将从分布式系统的角度使用简单的数据库类比来了解 CAP 定理。
CAP定理指出,在分布式系统中,当网络分区发生时,我们只能选择一致性或可用性。这是埃里克·布鲁尔(Eric Brewer)为了理解分布式系统而创造的。CAP 代表一致性、可用性和分区容错性。
现在,我们已经了解了CAP定理的定义。接下来,我们将了解它在设计或选择数据库、缓存、存储等分布式系统时如何发挥作用。
我们先通过一个简单的类比来理解。我们将向 MySQL 数据库插入一条记录。MySQL 服务器在单台机器上以单个进程运行,以处理读取和写入请求,如下图所示。
客户端想要读取记录并将其写入关系型 MySQL 数据库。由于数据库实例运行在单机上,系统将保持一致,这意味着客户端将看到最近的写入。如果节点发生故障或者客户端与数据库服务器之间出现网络故障,系统将不可用。
随着用户数量的增长,我们的数据库应该扩展更多的读取和写入。有多种方法可用于扩展数据库,但我们将讨论在复制或分区数据库时如何应用 CAP 定理。这就是分布式系统的实际应用。为了扩展更多的读取,对于主数据库中发生的每个更改,我们都会将数据从 mysql 主数据库复制到副本。这种方法有助于将写入和读取请求拆分到在不同计算机上运行的单独 MySQL 实例。
如下图所示,MySQL 实例运行在 master 上,master 接受写入请求。然后,所有写入都会复制到副本计算机中以处理读取请求。与之前的单实例设置相比,我们将写入和读取分离到不同的机器中。
现在,我们已经分发了 MySQL 数据库,它服务于主服务器的写入和读取并复制 MySQL 实例。让我们看看如何使用 CAP 定理来定义此 MySQL 设置。由于我们的数据库设置是分布式的,默认情况下它是分区容忍的,这意味着当某些节点发生故障时,系统应该处理一些客户端请求。
在上面的例子中,我们没有对数据库进行分区。相反,我们仅添加了复制来扩展读取请求。如果主节点发生故障,副本实例可用于服务读取请求。这与之前的单实例设置有点不同。CAP定理指出,在分布式系统中,我们只能选择一致性或可用性。
假设我们的数据库系统要求高度一致。当客户端发出请求时,它应该随时返回最新的数据。让我们考虑一个将记录写入主数据库的简单场景。
如果副本机器不可用,那么主数据库有两种选择,
如果我们选择第一个选择,我们会将错误返回给客户端。如果主实例和副本实例之间发生网络分区,我们的系统将保持高度一致。由于主实例和副本实例具有相同的数据,因此我们的客户端将读取最近的写入。我们的系统现在更多的是CP。
如果我们选择第二个选择,我们的系统将具有高可用性。它将向我们的客户端返回成功的响应并将写入存储到我们的本地计算机。我们的写入将在稍后的时间点异步复制。同时,如果写入主实例的客户端从副本实例中读取数据,它可能会也可能不会看到最新的数据。这是由于网络分区或网络故障导致异步复制延迟。
我们的系统现在更像是一个 AP,因为由于主服务器和副本服务器之间的网络分区,我们的客户端可能看不到只读副本中的最新数据。
在分布式系统中,不可能实现 CAP 的所有三个属性。我们只能选择其中的任意两个CAP,例如CA、CP、AP。CA没有任何意义。在大多数情况下,分布式系统是分区容忍的。所以,我们要么选择CP,要么选择AP。
当我们选择上例中的第一个选项来选择CP时,并不是说我们的系统将不可用。当主实例无法连接到副本实例时,我们的数据库将无法响应写入。在这种情况下,我们更看重一致性而不是可用性。
我们可以将分布式系统称为 CP 或 AP,因为这些属性在某些场景(例如网络故障)中受到青睐。在这里,我们不能牺牲 P(分区容错性),因为分布式系统默认是分区容错的。
因此,如果没有 P,我们就无法构建任何分布式系统。我们必须支持 C (CP) 或 A(AP) 来定义我们的系统。
在本文中,我们了解了 CAP 定理以及如何使用它来定义分布式系统的属性。当我们构建分布式数据库、缓存、存储等时,我们可以选择决定我们的系统应该如何表现。无论是在某些场景下必须支持一致性还是可用性,在本文中,我们已经了解了分布式 MySQL 只读副本的属性以及在网络故障期间我们可以从中得到什么。
更多技术干货请关注公号【云原生数据库】
squids.cn,云数据库RDS,迁移工具DBMotion,云备份DBTwin等数据库生态工具。
irds.cn,多数据库管理平台(私有云)。