
说人话、重实战、讲干货 我是程序员古德,你的专属软考顾问 本篇是我更新的第 452 篇软考原创文章,同时还提供软考报名咨询、备考规划、论文批阅、学习指导、应试答疑等多种服务。 只要是我亲身验证过的方法、踩过的备考坑,一定坦诚相告,有需求的小伙伴可以后台私信我。
CAP定理又称布鲁尔定理,由加州大学伯克利分校的计算机科学家埃里克布鲁尔于二零零零年在分布式计算原理研讨会上首次提出。当时布鲁尔并没有给出严格的数学证明,而是以猜想的形式抛出了这个后来深刻改变分布式系统设计范式的论断。二零零二年,麻省理工学院的塞思吉尔伯特和南希林奇在异步分布式系统模型中给出了形式化证明,将这一猜想确立为定理,从此CAP定理成为每一位分布式系统从业者和架构科目考生必须掌握的基础理论。
CAP三个字母分别代表了分布式系统中三个核心属性。一致性指的是在一个分布式系统的所有节点上,同一时刻看到的数据完全一致,任何读操作必须返回最近一次写操作的结果,或者说所有节点在执行写操作时的顺序必须全局统一。如果某个客户端向节点A写入了一个新值,另一个客户端立即从节点B读取,在满足一致性的系统中节点B必须返回刚刚写入的新值而非旧值。可用性的定义较为直接:每一个发往分布式系统中非故障节点的请求,必须在有限时间内收到一个非错误的响应,系统必须始终处于可响应状态。分区容错性是指当分布式系统的节点之间的网络通信出现故障即发生网络分区时,系统仍然能够继续提供正常的服务。网络分区在现实中极为常见,交换机故障、网线断开、网络拥塞导致的超时、数据中心之间的光缆中断,都属于分区的具体表现。
CAP定理的核心结论可以概括为一个简洁而有力的陈述:在一个分布式系统中当网络分区发生时,一致性、可用性和分区容错性三者最多只能同时满足其中两个。这句话需要精确理解,它说的是在网络分区已经发生的条件下系统必须在一致性和可用性之间做出选择,而分区容错性本身不是一个可选项,因为网络分区是客观存在的事实无法被消除只能被处理。许多初学者会把定理理解为分布式系统只能从三者中任选其二,这种理解忽略了分区容错性的特殊地位,导致CA系统被当成一种实际可行的架构选择来讨论,这是CAP定理学习中第一个需要纠正的常见误解。
CAP定理中提到的一致性并非一个笼统的概念,分布式系统领域对一致性有极为精细的分层定义。最强的一种一致性称为线性一致性或原子一致性,它要求所有操作看起来都是在一个单一的时间点上原子化执行的,而且每个操作的实际执行时间必须落在它的调用时刻和返回时刻之间的某个时间点。线性一致性给程序员提供了最接近单机编程的心智模型,但实现的代价极为高昂,通常需要借助分布式共识协议来保证操作的全序关系。
顺序一致性比线性一致性稍弱,不要求操作的实际时间顺序与全局真实时间对齐,只要求所有节点看到的操作执行顺序一致且每个节点自身的操作顺序得到保持。因果一致性进一步放松了要求,只规定存在因果关系的操作在所有节点上以相同的顺序被观察到,而并发操作之间没有因果关系的则允许各节点以不同顺序看到。最终一致性是分布式系统中应用最广泛的一致性模型,它只保证如果系统不再接收新的写入,那么经过足够长的时间之后所有节点上的数据最终会收敛到同一个值。DNS域名系统是最终一致性的经典实例,域名记录的变更可能需要几十分钟甚至几十小时才能传播到全球所有DNS缓存服务器,但只要没有新的变更写入最终所有DNS服务器都会返回相同的解析结果。
在CAP定理的语境中,C特指强一致性也就是线性一致性或至少是顺序一致性,绝不是最终一致性。这个区分在考试中经常成为命题的切入点,很多选项把最终一致性当成CAP定理中的C来讨论,如果考生没有区分清楚不同一致性模型的层次差异就很容易掉入命题人预先挖好的陷阱。理解了一致性模型的层次结构之后还需要注意,事务的隔离级别和分布式一致性是两个不同层面的概念,前者属于ACID事务模型的范畴后者属于分布式数据复制模型,二者虽然在语义上有交叉但不能混为一谈。
可用性这一概念表面上看似乎最为简单,但深入分析之后会发现它包含着若干微妙的边界条件。首先可用性要求响应必须在有限时间内返回,这意味着系统不能无限期地等待某个阻塞的操作完成,所有操作都必须有一个明确的时间上限也就是通常所说的超时机制。其次可用性不要求返回的数据一定是最新的,只要返回了一个非错误的值即可,哪怕这个值是过期的旧数据也算满足了可用性的定义。这一点至关重要,因为它暗示了在极端情况下为了保证可用性可以牺牲一致性,这正是AP系统设计的理论根基。
分区容错性在CAP定理中处于一个相当特殊的位置。很多人初学时会追问:能不能设计一个完全没有网络分区的分布式系统从而同时获得一致性和可用性呢?答案是否定的,因为网络分区不是一个设计层面的决定而是物理世界的客观规律。只要网络中存在交换机和路由器等物理设备这些设备就可能出现故障,只要数据包在网络中传输延迟和丢包就永远存在。在一个异步分布式系统模型中节点无法区分另一个节点是发生了故障还是网络产生了延迟,这一核心困难被称为FLP不可能性定理,它从数学上证明了在纯异步模型中不存在确定性的共识算法。认识到分区容错性的客观必然性之后,CAP定理的真正含义就变得清晰了:分布式系统必须在一致性和可用性之间做出取舍,分区容错性是一种必须接受的前提条件而不是一个选项。
在实际工程中选择CP还是AP取决于具体的业务场景。金融交易系统和分布式锁服务等场景对数据一致性要求极高,哪怕短暂的服务不可用也比出现数据不一致要好,这些场景适合选择CP架构。社交媒体动态展示和点击量统计等场景对数据一致性要求相对宽松,用户更在意服务是否随时可用而不是看到了几秒前的旧数据,这些场景适合选择AP架构。值得强调的是这里的CP和AP不是绝对的二元分类而是一个连续的光谱,现代分布式系统往往通过动态调节一致性和可用性的折中程度以适应不同的运行时条件。
在分布式系统的学术讨论中,ACID事务模型和CAP定理通常被对立地放在一起讨论。但CAP定理真正对应的并非ACID而是BASE理论,后者是互联网时代大规模分布式系统在工程实践中总结出来的设计哲学。BASE三个字母分别是基本可用、软状态和最终一致性的英文缩写。基本可用指的是当系统出现故障时允许损失部分可用性但绝不整体不可用,典型的表现形式包括响应时间变长和部分非核心功能被降级。软状态这个概念直接指出了分布式系统中数据状态不需要时刻保持一致,允许存在一个中间的过渡状态,这个过渡状态的持续时间取决于数据同步的延迟和系统的负载情况。最终一致性就是前面讨论过的模型,系统保证在没有新写入的前提下最终所有副本的数据会收敛一致。
BASE理论与ACID的关系不是简单的对立或替代,而是不同场景下不同的取舍策略。传统的关系数据库系统强调ACID特性,通过锁机制和两阶段提交等协议来保证事务的原子性、一致性、隔离性和持久性,这种策略非常适合银行的转账操作和订单的库存扣减这类不容出错的业务。但在用户规模达到数亿级别的互联网服务中严格的事务保证会严重限制系统的横向扩展能力,此时基于BASE理论的柔性事务和最终一致性方案就变得更加务实。电商平台的商品库存显示就是一个经典案例,当某个爆款商品同时被数万用户抢购时系统不可能对每次库存查询都走一遍严格的一致性协议,而是允许显示的库存数量和实际可售数量之间存在短暂的偏差,在订单提交环节再用最终的一致性检查来拦截超卖。
理解CAP定理和BASE理论的关系对于应对架构科目的考试题目有重要的实际意义。命题人有时候会故意混淆ACID和CAP的讨论语境,在题目中把数据库事务的一致性等同于分布式一致性,或者在讨论CAP取舍时突然插入ACID的概念来干扰判断。考生需要在阅读题干的瞬间就识别出题目讨论的是单机事务模型还是分布式数据复制模型,从而选择正确的理论框架来作答。
Paxos算法由莱斯利兰波特于一九九零年提出,但因为其证明过程过于艰涩难懂直到分布式系统大规模普及之后才被业界广泛采用。Paxos算法解决的核心问题是:在一个可能存在节点故障和网络分区的异步分布式系统中如何让多个节点就某个值达成一致。算法的参与者分为提议者、接受者和学习者三种角色,一个典型的Paxos执行过程分为准备阶段和接受阶段两个阶段。在准备阶段提议者生成一个全局唯一的递增提案编号并向超过半数的接受者发送准备请求,接受者收到请求后如果该编号大于自己之前见过的任何编号则承诺不再接受编号更小的提案并返回自己已经接受过的最大编号的提案值。在接受阶段提议者根据收到的大多数回复选择一个值,如果发现已经有接受过的值则必须沿用该值,然后向接受者发送接受请求要求确认该值,只要获得超过半数的确认本轮共识即告完成。
Paxos算法有两个需要特别注意的精妙设计点。第一是提案编号的全序关系保证了算法的安全性,即永远不会出现两个不同的值同时被选中的情况。第二是提议者在第二阶段必须选择已有最大值对应的值的强制规则保证了即使多个提议者同时发起提案最终达成的共识值也不会产生冲突。在架构科目的考试中Paxos算法通常不会要求手写伪代码,但考生需要理解其两个阶段的基本职能和过半数的法定人数机制,这些都是选择题和简答题的高频得分点。
Raft协议是斯坦福大学的迭戈翁加罗和约翰奥斯特豪特于二零一四年提出的一种共识算法,其设计目标是用更易于理解和实现的方式提供与Paxos等价的功能。Raft将共识问题分解为三个相对独立的子问题,分别是领导选举、日志复制和安全性保证。在Raft集群中每个节点在任意时刻都处于领导者、跟随者或候选者三种角色之一,正常运行时只有一个领导者负责处理所有客户端的写请求,其他节点都是跟随者被动地复制领导者的日志。领导者周期性地向跟随者发送心跳消息来维持自己的权威地位,如果跟随者在一个选举超时的时间范围内没有收到领导者的心跳就会转变为候选者,增加自己的任期编号并发起新的选举。
Raft的领导选举采用随机化超时机制来避免选票分裂,每个节点的选举超时时间在一定范围内随机取值,这样可以大大降低多个候选者同时发起选举导致平票的概率。当候选者获得超过半数节点的投票时即当选为新领导者,随后立即向所有节点发送心跳消息宣告自己的领导地位。被领导者发送的心跳或选举请求中包含的任期编号是Raft中一个关键的逻辑时钟,节点只接受任期编号不小于自身当前任期的消息,任期编号较小的消息会被直接忽略,这种简单而有效的机制保证了在任何网络条件下都不会出现同时存在两个合法领导者的脑裂现象。
软考命题中关于CAP定理最常见的陷阱之一就是试图混淆没有分区和有分区两种场景下的结论。很多人会在学习之后产生一个疑问:如果网络没有发生分区那岂不是三者可以同时满足吗?从纯理论角度看这个说法本身并没有错,因为CAP定理的前提条件就是网络分区已经发生,如果分区不存在同时满足一致性和可用性确实没有问题。但命题人会利用这个表述的模糊性在选项中设置干扰项,比如在题干中讨论某个实际分布式系统时给出该架构同时满足CAP三个属性的说法作为选项,因为实际网络中分区不可避免所以这个选项显然错误,如果考生没有形成分区必然存在的直觉就容易被迷惑。
另一个相关的命题套路是将CAP定理中的一致性与数据库事务的ACID一致性混为一谈。有的题目会这样表述:关系数据库通过事务机制同时满足了CAP定理中的一致性和可用性。这种说法的错误在于关系数据库的事务一致性是指数据满足所有预定义的约束条件比如外键约束和唯一性约束,而CAP定理中的一致性是指分布式数据副本之间的一致,二者虽然共享中文的一致性这个叫法但在英文文献中分别对应Consistency的不同层面。对于单机关系数据库而言它根本就没有数据复制和分区的问题,所以CAP定理根本不适用于单机数据库场景。
在应对选择题时考生可以训练一种快速的题干关键词定位技巧,只要看到分布式系统数据副本网络分区三个关键词同时出现或隐含出现就应该默认切换到CAP定理的分析框架中。如果选项中出现了CA架构这样的表述可以无脑判定为错误选项,因为在存在网络分区的真实分布式系统中CA架构就像永动机一样只是理论上的理想模型。同样如果一个选项声称某系统同时满足强一致性和高可用性且部署在跨地域的数据中心之间,这也是一个典型的错误表述,跨地域的网络延迟必然导致分区的可能性无法消除,强一致性和高可用性只能是二选一的取舍关系。这些快速辨析技巧在考场上可以大幅提高答题的速度和正确率。
另一个值得注意的辨析点涉及最终一致性和CAP定理的一致性之间的关系。有的题目会这样出:该分布式数据库采用了最终一致性模型所以满足了CAP定理中的一致性要求。这种表述显然是错误的,CAP定理中的C要求的是强一致性也就是线性一致性,最终一致性对应的是牺牲一致性换取可用性的AP路线。考生必须清楚地记得选择最终一致性就意味着放弃了CAP定理中C的要求而不是实现了C。把这个逻辑关系理顺之后凡是选项中将最终一致性与CAP定理中的C画等号的都可以直接排除。
在系统架构设计师的历年考试中,CAP定理多次作为核心考点出现在上午选择题部分。二零一七年的一道真题考察了考生对CAP定理三个属性基本含义的理解,题干给出了一个分布式电商系统在多数据中心部署的场景描述,要求考生分析在发生网络分区时系统应该如何做出取舍。这道题的命题思路非常典型,通过一个具体的业务场景将抽象的理论问题具象化,考察考生在实际环境中应用CAP定理分析问题的能力。正确选项应该指向电商系统的商品浏览功能对高可用性的需求高于强一致性因此在分区时倾向于AP策略,但下单支付环节必须使用CP策略来保证资金安全。
二零一九年的一道选择题直接将CAP和BASE并列考察,题干列出了四个关于分布式系统设计原则的陈述要求考生选出正确的组合。其中一个干扰陈述声称在一个分布式系统中同时实现强一致性和高可用性是完全可行的而且大多数互联网公司都是这么做的,如果考生清楚CAP定理的基本结论这个选项可以立刻排除。另一个干扰陈述说分区容错性只是理论上的概念实际工程中可以通过冗余网络设备彻底消除网络分区,这个表述同样违反了CAP定理的前提认知即分区不可避免。这类题目的解题思路不是死记硬背而是建立正确的理论框架然后用框架去过滤选项。
CAP定理与分布式一致性的备考应该从建立层次化的知识框架开始入手。第一层是要掌握CAP三个属性的精确定义,尤其是一致性在CAP语境中特指强一致性而非最终一致性这个高频考点。第二层是理解分区容错性在CAP定理中的特殊地位即分区不可避免因此实际的取舍只在CP和AP之间进行。第三层是掌握BASE理论的基本内涵并能够清楚地辨析ACID事务模型与CAP定理的适用场景差异。第四层是理解Paxos和Raft两种典型分布式一致性协议的核心机制和各自的特点,重点是过半数的法定人数规则、任期编号的逻辑时钟作用和两阶段提交的基本流程。
从应试策略的角度来看CAP定理相关题目在架构科目中属于性价比极高的考点,主要是因为其核心结论简洁明确不容易产生歧义,但命题人又会通过各种细节来设置干扰项,所以只要考前做过充分的辨析训练考场上这部分题目基本可以做到零失误。建议在复习时重点练习如何快速识别题干中关于CA架构和最终一致性等于CAP一致性的错误表述,形成条件反射式的排除能力。同时对于Paxos和Raft的对比也不要只背概念,最好能够用自己的语言讲清楚为什么Paxos需要两个阶段而Raft要引入领导者角色,这样在遇到灵活的应用型题目时才能得心应手。
分布式一致性这个知识模块虽然在软考的整个知识体系中所占篇幅不大,但它实际上起到了串联多个科目知识点的作用。理解了一致性协议的过半数的法定人数机制之后考生在复习网络规划科目中关于集群容错和故障检测的知识点时会有更深的理解,掌握了CAP取舍之后再看数据库科目中的数据复制与分片策略也会豁然开朗。正因为如此建议不要孤立地学习CAP定理和分布式一致性,而是在复习过程中主动寻找它与其他知识模块之间横向的联系,构建一个融会贯通的知识网络。
本篇完!