前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >分布式 CAP 定理的前世今生

分布式 CAP 定理的前世今生

作者头像
恋喵大鲤鱼
发布2022-06-19 14:53:17
3660
发布2022-06-19 14:53:17
举报
文章被收录于专栏:C/C++基础C/C++基础

文章目录

CAP 理论在互联网界有着广泛的知名度,知识稍微宽泛一点的工程师都会把其作为衡量系统设计的准则。大家都非常清楚地理解了 CAP 定理:任何分布式系统在一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三个方面不能兼得,最多只能得其二。因此,任何分布式系统的设计只是在三者中的不同取舍而已。 事实上,让人吃惊的是 CAP 在国外的影响力完全不如所想,相反还伴随着诸多的争论。下面我们系统地阐述一下 CAP 的来龙去脉。

1.CAP 的历史

1985 年,三位学者 Fischer、Lynch 和 Paterson 共同证明了异步通信中不存在任何一致性的分布式算法,该结论被称之为 FLP Impossibility(FLP 是三位作者名字的首字母缩写)。基于此,人们开始寻找分布式系统设计的各种因素。一致性算法既然不存在,但若能找到一些设计因素,并进行适当的取舍以最大限度满足系统需求成为当时的重要议题。比如,在 CAP 之前研究者就已经发现低延迟和顺序一致性不可能同时被满足。

2000 年,Eric Brewer 教授在分布式计算原理研讨会(PODC)的研讨会上提出了一个猜想:一致性、可用性和分区容错性三者无法在分布式系统中被同时满足,并且最多只能满足其中两个!

这个猜想首次把一致性、可用性和分区容错三个因素提炼出来作为系统设计的重要特征,断言用此三者可以划分所有的分布式系统,并指明这三个特征之间的不可能性关系。Brewer 猜想比单纯的“低延迟和顺序一致性不能被同时满足”的结论更具体,对实际系统的构建也更具可操作性。

Brewer 教授当时想象的分布式场景是 webservice,一组 websevrice 后台运行着众多的 server,对 service 的读写会反应到后台的 server 集群,并对 CAP 进行了定义:

  • C(Consistency:一致性):所有的节点上的数据时刻保持同步。

这里的一致性指的是强一致性,也就是数据更新完,访问任何节点看到的数据完全一致,要和弱一致性,最终一致性区分开来。

  • A(Availability:可用性):每个请求都能接收到一个响应,无论响应成功或失败

这里的可用行还包括不能出现延迟,比如如果节点B由于等待数据同步而阻塞请求,那么节点B就不满足高可用性。也就是说,任何没有发生故障的服务必须在有限的时间内返回合理的结果集。

  • P(Partiton tolerence:分区容错):系统应该能持续提供服务,即使系统内部有消息丢失(分区)

这里的分区是指网络意义上的分区。由于网络是不可靠的,所有节点之间很可能出现无法通讯的情况,在节点不能通信时,要保证系统可以继续正常服务

高可用、数据一致是很多系统设计的目标,但是分区又是不可避免的事情:

  • CA without P:如果不要求P(不允许分区),则C(强一致性)和A(可用性)是可以保证的。但其实分区不是你想不想的问题,而是始终会存在,因此CA的系统更多的是允许分区后各子系统依然保持CA。
  • CP without A:如果不要求A(可用),相当于每个请求都需要在Server之间强一致,而P(分区)会导致同步时间无限延长,如此CP也是可以保证的。很多传统的数据库分布式事务都属于这种模式。
  • AP wihtout C:要高可用并允许分区,则需放弃一致性。一旦分区发生,节点之间可能会失去联系,为了高可用,每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。现在众多的NoSQL都属于此类。

CAP 的出现仿佛是一盏明灯,它揭露了分布式系统的本质,并给出了设计的准则,而这正是1985年以来人们正在寻找的东西。所以 CAP 在当时的影响力是非常大的!

2.CAP 被上升为定理

2002 年,Lynch 与其他人证明了 Brewer 猜想,从而把 CAP 上升为一个定理。但是,她只是证明了 CAP 三者不可能同时满足,并没有证明任意二者都可满足,所以,该证明被认为是一个收窄的结果。

Lynch 的证明相对比较简单:采用反正法,如果三者可同时满足,则因为允许 P 的存在,一定存在 Server 之间的丢包,如此则不能保证 C,证明简洁而严谨。

在该证明中,对 CAP 的定义进行了更明确的声明:

  • C:一致性被称为原子对象,任何的读写都应该看起来是“原子“的,或串行的。写后面的读一定能读到前面写的内容。所有的读写请求都好像被全局排序
  • A:对任何非失败节点都应该在有限时间内给出请求的回应。(请求的可终止性)
  • P:允许节点之间丢失任意多的消息,当网络分区发生时,节点之间的消息可能会完全丢失

该定义比 Brewer 提出的概念清晰了很多,也显得更加正式化!

3.前所未有的质疑

当国内工程师对 CAP 痴迷的时候,国外的工程师和研究者对 CAP 提出了各种质疑,纷纷有用反例证明着 CAP 在各种场合不适用性,同时挑战着 Lynch 的证明结果!

纵观这些质疑,基本都是拿着一个非常具体的系统,用CAP的理论去套,最后发现要么CAP不能Cover所有的场景,要么是CAP的定义非常模糊,导致自相矛盾!一句话,把 CAP 接地气是非常困难的!

你是否看了 CAP 的概念定义后还是感觉很模糊?如果是,你并不孤独,有很多人都是如此!

CAP 没有考虑不同的基础架构、不同的应用场景、不同的网络基础和用户需求,而 C、A、P 在这些不同场景中的含义可能完全不同,这种无视差异化的定义导致了非常大的概念模糊,同时也变成 CAP 被质疑的源头!

3.1 质疑 1:概念混乱,废话一堆,不能作为定理

在论文 Deconstructing the `CAP theorem’ for CM and DevOps 中,作者对 CAP 发起了强烈的挑战,强烈谴责了 CAP 模糊不一致的概念:

  • 在 CA 中的 C 代表的是本地一致性;CP 中的 C 代表的是全局一致性,AP 中直接没有 C;这些 C 的含义在不同的场景根本就不同。终端- - 用户 agent 该不该引入到 CAP 中?CAP 到底是说一个 agent 的多次更新,还是多个用户的一次更新?没有 agent 参与的系统谈什么一致性?
  • 如果分区发生在系统内部(水平分区),对 agent 而已并没有影响;若分区发生在 agent 与系统间(垂直分区),这种情况对 DNS 系统架构的可用性根本没有任何影响;但对银行事务架构却有巨大影响。也就是说,可用性、分区容错,是两个相关切无法独立切分的概念。

一句话:CAP 说了一些永远不存在的废话!作为一个严格的数学定理,一定要概念清晰并且可自证明,CAP 显然不具备这个条件,并声称“绝不承认其为一个定理”!

论文作者对相对论有相当的理解,从相对论来看,每个节点都只知道自己的结果,永远无法得知其他节点的情况,系统整体是否一致我怎么会知道?

并且作者对一致性、可用性归结为一个非常深刻的见解:一切都是时间视图!多长时间返回结果算可用?多长时间返回认为不可用?多长时间数据同步算一致?因此,一切的本质是时间!

根据时间特性和相对论,作者提出了一个独创的 promise 系统模型,每个节点都对自己的行为在有限时间内进行承诺,其他节点根据这个承诺和自己的状态决定本地如何处理。

作者还上传了自己的笔记拍照,我大体看了下,基本上是构建了一个基于时间同步的有限状态机。实际上 Lynch 早就证明,在同步环境下一致性是可以达到的!

3.2 质疑 2:不适用于数据库事务架构

Errors in Database Systems, Eventual Consistency, and the CAP Theorem 的作者,详细地列举了分布式事务中可能的分区情况,比如说应用因为更新一些错误的数据而导致失败,此时无论使用什么样的高可用方案都是徒劳,因为数据发生了无法修正地错误!作者还列举了其他一些情况,虽然分区发生但无法保持高可用,这就说明了CAP并不能用来完全解释数据库事务架构。

作者还建议,应该放弃分区容错,因为在局域网中分区很少发生;而在广域网中,有各种备选方案,导致实际上的分区也较少发生。

3.3 质疑 3:应该构建不可变模型避免 CAP 的复杂性

How to beat the CAP theorem 一文的标题就是锤死 CAP,可见作者对 CAP 的不屑溢于言表!

作者认为 CAP 的困境在于允许数据变更,每次变更就得数据同步,保持一致性,这样系统非常复杂。

他认为数据就是客观存在的,不可变,只能增、查。传统的 CURD 变为 CR。这个概念非常类似 Cassandra 中的顺序写的概念,任何的变更都是增加记录。通过对所有记录的操作进行合并,从而得到最终记录。

因此,作者认为任何的数据模型都应该抽象为:Query=Function(all data),任何的数据试图都是查询,查询是对全体数据施加了某个函数的结果。这个定义清晰简单,完全抛弃了 CAP 那些繁琐而又模糊的语义。因为每次操作都是对所有数据进行全局计算,也就没有了一致性问题!

有这样的系统吗?有,Hadoop 便是!作者认为,Hadoop 的 HDFS 只支持数据增加,而 Mapeduce 却进行全局计算,完美地符合了他对数据处理的期望!

Hadoop 也存在某个节点数据丢失的问题,但随着流式计算,丢失的数据终究会随着系统的正常而被最终合并,因此数据最终是一致的。

Hadoop 不能进行实时计算咋办?作者又构建了一套基于 Cassandra 和 ElephantDB 的实时数据处理系统。搞得无比复杂!

3.4 质疑 4:分区容错概念有误导

cap-confusion-problems-with-partition-tolerance 一文的作者质疑了 Errors in Database Systems, Eventual Consistency, and the CAP Theorem 作者的观点,但是比较清晰地揭露了 CAP 概念之间的模糊。

作者认为可用性和一致性是分布式系统的属性,而分区却是网络的一个属性。不能在问题发生时是否选择要不要分区,而是应该在分区既定的情况下选择要一致性还是可用性。网络分区会发生在两种情况:

Errors in Database Systems, Eventual Consistency, and the CAP Theorem 文中所谓的分区就是情况 1,每个独立的子网还能正常运作,作者认为这种分区条件非常苛刻,更倾向于认为这只是分区可用性的一种度量方式(发给每个子网的请求都有正确的 Response)。

而实际上,因为机器原因发生的分区情况更常见一些,如果“很多”机器都发生故障,系统会因为一个“多数派”的丢失而导致不可用(比如,因为多数不存在,最新的读可能无法读取到上一次的写)。一句话:分区也同时蕴涵着不可用,这两个概念之间存在重叠。

作者认为,CAP 比较合理的表达方式应该是:在一个允许网络发生故障的系统中,该选择一致性还是可用性?

当系统的机器数量持续增加时,一致性会加剧时延,维护一致性的成本会非常之高,因此我们基本就剩下一种选择:在允许网络失败的系统中,更多地是选择可用性。而 Zookeeper、Hadoop 之所以选择一致性,是因为这些系统多数是由在同一集群的少数节点构成!

作者其实间接地否认了“3个中同时满足2个”这样的误解,而是从更深层次探讨了 CAP 的本质,但并没有试图推翻 CAP。

4.对质疑的回应

面对大量的质疑,Brewer和Lynch终于坐不住了,因此两人纷纷出来澄清:

Brewer 于 2012 年重申:

  • “3 个中的 2 个”这个表述是不准确的,在某些分区极少发生的情况下,三者能顺畅地在一起配合
  • CAP 不仅仅是发生在整个系统中,可能是发生在某个子系统或系统的某个阶段

该声明并不否认像质疑 3 那种三个因素协同工作的情况,并把 CAP 应用在一些更细粒度的场景中。

Lynch 也在 10 年后的 2012 年重写了一篇关于 CAP 的论文 Perspectives on the CAP Theorem,该论文主要做了几件事:

  • 把 CAP 理论的证明局限在原子读写的场景,并申明不支持数据库事务之类的场景
  • 一致性场景不会引入用户 agent,只是发生在后台集群之内
  • 把分区容错归结为一个对网络环境的陈述,而非之前一个独立条件。这实际上就是更加明确了概念
  • 引入了活性(liveness)和安全属性(safety),在一个更抽象的概念下研究分布式系统,并认为 CAP 是活性与安全属性之间权衡的一个特例。其中的一致性属于 liveness,可用性属于 safety。
  • 把 CAP 的研究推到一个更广阔的空间:网络存在同步、部分同步;一致性性的结果也从仅存在一个到存在 N 个(部分一致);引入了通信周期 round,并引用了其他论文,给出了为了保证 N 个一致性结果,至少需要通信的 round 数。也介绍了其他人的一些成果,这些成果分别都对 CAP 的某一个方面做出了特殊的贡献!

其实 Lynch 的论文主要就是两件事:缩小 CAP 适用的定义,消除质疑的场景;展示了 CAP 在非单一一致性结果下的广阔的研究结果!并顺便暗示 CAP 定理依旧正确!

从此论文还是可以看出,Lynch 的功力高出其他质疑者好多!

5.如何看待CAP?

首先肯定的是,CAP 并不适合再作为一个适应任何场景的定理,它的正确性更加适合基于原子读写的 NoSQL 场景。质疑虽然很多,但很多质疑者只是偷换概念,并没有解决各个因素之间的取舍问题。而无论如何,C、A、P 这个三个概念始终存在任何分布式系统,只是不同的模型会对其有不同的呈现,可能某些场景对三者之间的关系敏感,而另一些不敏感。在所有的质疑当中,质疑 4 是分析的比较中肯的,其清晰的概念分析该让我们对 CAP 有更深入的理解!

就像 Lynch 所说,现在分布式系统有很多特性,比如扩展性、优雅降级等,虽着时间的发展,或许这些也会被纳入研究范畴,而作为开发者,这都是我们需要考虑的问题,而不仅是 CAP 三者!


参考文献

Practical Understanding of FLP Impossibility for Distributed Consensus wikipedia.CAP定理 Deconstructing the `CAP theorem’ for CM and DevOps Errors in Database Systems, Eventual Consistency, and the CAP Theorem How to beat the CAP theorem cap-confusion-problems-with-partition-tolerance Perspectives on the CAP Theorem

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-06-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 1.CAP 的历史
  • 2.CAP 被上升为定理
  • 3.前所未有的质疑
    • 3.1 质疑 1:概念混乱,废话一堆,不能作为定理
      • 3.2 质疑 2:不适用于数据库事务架构
        • 3.3 质疑 3:应该构建不可变模型避免 CAP 的复杂性
          • 3.4 质疑 4:分区容错概念有误导
          • 4.对质疑的回应
          • 5.如何看待CAP?
          • 参考文献
          相关产品与服务
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档