大家好,欢迎来到Tlog4J课堂,我是Jensen。分布式CAP定理大家都很熟悉了。CAP指的是分布式系统中的三个特性:我在之前的文章中也提到过——CAP是分布式系统中的三维“客户承诺”:一致性(Consistency):要么我会返回你一个错误,要么我会返回给你绝对一致的最新数据,强调数据是正确的。可用性(Availability):我一定会给你返回数据,不会给你返回错误,但我不保证数据是最新的,重点是服务没有错误。PartitionTolerance(分区容错):我会一直跑下去,不管我内部出现什么样的数据同步问题,强调的是不要挂掉。在JeffHodges的优秀博文注释中,他建议我们使用CAP定理来评论分布式系统,许多人听取了这个建议,将他们的系统描述为“CP”(一致性但在网络分区时不可用)、“AP”(可用但在网络分区期间不一致)或有时是“CA”。这一次,我们再深入探讨一下,按照CP/AP来划分不同的系统是否合理。回顾一致性,我们首先要明白数据一致性问题存在于计算机软硬件层面的数据拷贝的任何一个环节,比如CPU和内存之间的数据拷贝,内存之间的数据拷贝,内存之间的数据拷贝。和磁盘。,计算机之间的网络通信等分布式系统是以软件系统为基础的,将系统分布在不同的计算机上,必然会造成网络通信延迟或网络分区。我们目前的计算机技术不能100%解决一致性问题。CAP中的一致性意味着线性化。这是一种非常特殊且非常强的一致性。ACID中的C虽然也是一致性,但是和CAP的一致性没有关系。那么什么是线性化?例如:如果操作B成功完成操作A,那么整个系统必须显示操作A已完成或更新操作B。此图显示Alice和Bob在同一个房间里检查他们的手机以获取最终结果2014年世界杯。就在最终结果公布之后,爱丽丝刷新了页面,看到了获胜者的公告,她很高兴地告诉鲍勃。Bob也立即在手机上重新加载了页面,但是他的请求被发送到数据库的副本,产生结果的数据还没有得到,结果手机上还在进行决赛.如果Alice和Bob同时刷新,得到不同的结果也就不足为奇了,因为他们不知道自己的请求中的哪一个先被特定的服务器处理了。但是Bob知道Alice告诉他最终结果后他刷新了页面,所以他期望自己查询的结果一定比Alice的更新,但实际上他得到的是旧结果,这就违反了线性一致性。只有当Bob通过另一个通信渠道知道Alice的结果时,Bob才能知道他的请求一定是在Alice之后。如果鲍勃没有听爱丽丝说游戏结束了,他也不知道他看到的结果是旧的。如果你正在构建一个数据库,你不知道用户会有哪些其他的沟通渠道,所以如果你想提供可线性化的访问,你需要让你的数据库看起来只有一个副本,即使它可能有多个多处备份。这是一个非常昂贵的属性,因为它需要你做大量的协调工作,甚至你计算机上的CPU也不提供对本地内存的线性化访问!在现代CPU上,需要使用MemoryBarrier指令来实现线性化访问,甚至测试一个系统是否可线性化都非常困难。所以抛开专注谈一致性,意义不大。回顾可用性可用性在CAP中被定义为“每个请求必须返回一个[非错误]结果,如果它被一个工作的[数据库]节点接收到”。请注意,仅某些节点能够处理此请求是不够的。任何工作节点都必须能够处理此请求。因此,许多号称高可用的系统通常不符合这里的可用性定义,它们就这样失败了。转移或断路器降级。CAP根本没有提到延迟,我们实际上更关心延迟而不是可用性。事实上,满足CAP可用性的系统可以在保持可用性属性的同时花费任意长的时间来回复请求。但是如果你的系统需要两分钟来加载一个页面,你的用户永远不会认为它是“可用的”,这就是为什么现在大多数互联网项目只允许请求延迟2到10秒的原因。CP和AP的权衡CAP定理只考虑了网络分区失效的情况(比如所有的节点都还在运行,但是它们之间的网络已经不工作了),这种失效是肯定会发生的,但是这个不是唯一会发生故障的地方。节点可能会崩溃或完全重启,你可能没有足够的磁盘空间,你可能会遇到软件错误(bug)等。在构建分布式系统时,你需要考虑更多的问题,如果过于关注CAP很容易导致忽略其他重要问题。那么为什么我们要在网络分区的情况下放弃可用性和一致性之一呢?例如:你的数据库在两个不同的数据中心有两个副本。你如何备份它并不重要。可以是Single-Master,也可以是多个Leader,也可以是Quorum-basedbackup,要求数据写入一个数据中心的时候,也必须写入另一个数据中心。假设Client只连接其中一个数据中心,连接两个数据中心的网络出现故障,网络中断就是我们所说的网络分区,接下来会发生什么?我们有两个选择:应用程序仍然允许在写入数据库时??,两边的数据库仍然是完全可用的。但是一旦两个数据库之间的网络出现故障,任何一个数据中心的写操作都不会同步到另一个数据中心。这违反了线性一致性(使用前面的示例,Alice可能连接到数据中心#1,而Bob连接到数据中心#2)。如果你不想失去线性化,你必须保证你的读写操作在同一个数据中心,你可以称它为Leader,另一个数据中心,因为网络故障无法更新,你必须停止接收读写写操作,直到网络恢复,双方数据库再次同步。所以非Leader数据库虽然运行正常,但是无法处理请求,违反了CAP的可用性定义。这实际上是CAP定理的证明。我们这里的例子使用了两个数据中心,但它也适用于一个数据中心的网络故障。这里之所以使用两个数据中心,是为了更容易考虑这个问题。当一个系统可线性化,即CAP不可用时,并不意味着网络分区一定会导致应用停止。如果能将用户流量导流到Leader数据库,那么用户根本不会察觉到任何问题。实际应用中的可用性并不等同于CAP可用性。我们应用程序的可用性主要由SLA衡量。例如,99.9%正确的请求必须在一秒内返回成功。这实际上是一个整体测量。但是,无论一个系统是否满足CAP可用性,它实际上都能满足这样的SLA。在实际运行中,跨多个数据中心的系统往往是异步备份的,因此是不可线性化的。但之所以做出这样的选择,往往是因为远距离的网络延迟,而不仅仅是为了应对数据中心的网络故障。写在最后,CAP定理其实是一个简化的理论,以至于被大众普遍误解。实际上,CAP是一个非常精确的定义。事实上,大多数软件并不属于CP/AP这两类,但人们仍然将软件强行归入这两类,这就不可避免地为了应用而改变“一致性”或“可用性”的定义。的定义变了,CAP定理本身不适用,所以CP/AP划分完全没有意义。所以在技术面试的时候,我绝对不会问“哪些框架是CP,哪些框架是AP”的问题。问的意义不大。另一方面,CAP也是一个被广泛接受的分布式基础理论。很多框架也可以通过不同的配置实现广义上的CP/AP。与其花时间跟别人解释一个系统怎么按CP/AP划分不合理,不如坦然接受现状,但别忘了,你心里一定有自己的答案。自己想想,保持好奇和耐心。
