通过在物流系统中的应用实践,带你理解分布式系统的CAP定理

CAP定理,这个名字你可能听过无数次,但你真的了解它吗?本文将从似懂非懂的CAP定理入手,深入理解「分区」的关键因素,探讨CAP的进阶版本:PACELC,帮助你在十分钟内理解CAP定理。

目录

    1. 前言:似懂非懂的CAP定理
    1. 对「分区」的理解是关键因素
    1. CAP的进阶版本:PACELC
  • 3.1 只有分区出现时,才需要抉择A和C

  • 3.2 没有分区问题时,需要考虑L和C

  • 4. PACELC对我们的启发

1. 前言:似懂非懂的CAP定理

大名鼎鼎的CAP定理,相信很多人都听过,但具体是什么意思,对我们日常工作有什么指导价值呢?最近在学习数据架构,翻阅了一些资料,发现能讲明白的比较少。比如,CAP定理在百度百科中,它是这么解释的:

CAP原则又称CAP定理,指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。

  • 一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
  • 可用性(A):保证每个请求不管成功或者失败都有响应。
  • 分区容忍性(P):系统中任意信息的丢失或失败不会影响系统的继续运作。

再来看维基百科的词条解释:

  • 一致性(Consistency)(等同于所有节点访问同一份最新的数据副本)
  • 可用性(Availability)(每次请求都能获取到非错的响应——但是不保证获取的数据为最新数据)// Every request receives a (non-error) response, without the guarantee that it contains the most recent write.
  • 分区容错性(Partition tolerance)(以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。)

理解CAP理论的最简单方式是想象两个节点分处分区两侧。允许至少一个节点更新状态会导致数据不一致,即丧失了C性质。如果为了保证数据一致性,将分区一侧的节点设置为不可用,那么又丧失了A性质。除非两个节点可以互相通信,才能既保证C又保证A,这又会导致丧失P性质。

维基百科中对于可用性的描述,「非错的响应」跟「不管成功或失败都有响应」的描述应该是同一个意思,但明显有歧义;单纯看这两个定义非常的晦涩和抽象。比如,「分区容错性」到底是什么意思呢?CAP的一致性一般是指「强一致性」,但现实中的分布式系统大量都是最终一致性,它是否还具备指导意义?还有还有一些文章会结合着ACID,BASE一起讲,概念叠概念,缩写加缩写,看得我也是云山雾罩。

这些问题困扰了我好久,本篇文章算是自己的一篇笔记,如有不正确的地方,欢迎批评指正。

// 核心观点,省流不看版本

  • 当我们谈论“分区”时,就是在指节点之间的通信已经中断或不可达,形成两个或多个独立运行的分区;
  • 只有分区出现时,才需要抉择A和C;
  • 没有通信问题时,需要选择延迟L和C。

2. 对「分区」的理解是关键因素

「分区容错性」在很多文章中被解释为:系统可以在网络分区情况下继续运行。但这句话过于抽象,应该如何理解?

在分布式系统中,节点分布在不同的机器、不同的网段,甚至不同的机房内。当网络故障时,会把系统分成两个或多个独立的运行单元。而当我们谈论“分区”时,就是在指节点之间的通信已经中断或不可达,形成了两个或多个分区。

通过几道测试题,验证你是否真的懂了

Q1

点击空白处查看答案

如果系统的节点都分布在同一个机房,这个系统还会出现分区吗?

是。即使在同一个机房内,分布式系统设计者仍然需要考虑到分区容错性。事实上,在现代的云架构和微服务架构中,即使在同一数据中心内,设计者仍然假设分区是可能发生的,并使用合适的策略和技术来应对这种情况。

Q2

点击空白处查看答案

如果系统有10台机器,无状态地提供服务,这个系统还是出现分区的吗?

是。当我们谈论分区容错性或网络分区时,我们指的是系统中某些机器可能由于网络原因而无法与其他机器通信。这与系统是否有状态或无状态无关。

Q3

点击空白处查看答案

所有的分布式系统都可能出现分区,对吗?

对。任何涉及多台计算机之间网络通信的分布式系统都可能遭遇网络分区,无论网络基础设施有多可靠,总存在失败的可能性。

Q4

点击空白处查看答案

在物流供应链系统中,会有多个子系统;订单从电商系统进入到物流履约系统、再经过处理进入仓储系统、打包出库后进入配送系统,最后进入末端站点系统;如果把整个供应链看成一个大的系统的话,这多个子系统是否可以理解为多个「分区」?

不可以。这些子系统有独立的职责,它们在正常操作中并不被视为不同的“分区”,而是正常和预期的数据交换。但是,如果在某些情况下,例如由于网络问题或其他故障,导致物流履约系统无法与仓储系统通信,那么在那个特定时刻,这两个子系统可以被视为处于不同的“分区”。

由于分布式系统中,总是可能存在因网络原因导致的“分区”存在,所以CAP定理可以退化为是选择CP还是选择AP的问题,即分布式系统需要在「可用性」和「一致性」之间作出选择。看起来好像变简单了,但我再问你:

Q

点击空白处查看答案

在分布式系统中,是否可能不存在分区?

是。在上文中,我说**「当我们谈论“分区”时,就是在指节点之间的通信已经中断或不可达**,形成两个或多个独立运行的分区」。节点之间的通信当然可能恢复,当网络没有问题的时候,就可以理解为不存在“分区”了。而当没有分区P的时候,我们自然不需要做可用性和一致性的抉择,鱼和熊掌我们都要。

你有没有发现,CAP并没有考虑一个分布式系统中的重要因素?分布式系统的关键特性在于,系统中的组件通常在物理上是分散的,并且在运行时彼此独立,分布式系统之间的相互通信必须要考虑到「网络延迟」。对,CAP忽略的重要因素就是「延迟」,Latency。

3. CAP的进阶版本:PACELC

CAP定理是Eric Brewer在2000年提出的猜想,虽然在2002年得到了证明,但距离现在已经有20多年,我们大可抱着怀疑的态度来审视它。事实上,Eric Brewer自己在2012年写过一篇文章对CAP定理做了一版更新的解释:CAP Twelve Years Later: How the “Rules” Have Changed,其中补充了对延迟的描述

In its classic interpretation, the CAP theorem ignores latency, although in practice, latency and partitions are deeply related. Operationally, the essence of CAP takes place during a timeout, a period when the program must make a fundamental decision-the partition decision:

  • cancel the operation and thus decrease availability.
  • proceed with the operation and thus risk inconsistency.

在其经典的解释中,CAP 定理忽略了延迟,尽管在实践中,延迟和分区是密切相关的。在操作上,CAP 的本质发生在一个超时期间,一个程序必须做出一个基本决策的时期——分区决策:

  • 取消操作,降低可用性
  • 继续操作,存在一致性的风险

2010年耶鲁大学Daniel J. Abadi提出的PACELC可以看作是CAP定理的一个扩展或是校准。不要被PACELC这么多字母吓到了,它其实很简单,核心说了两件事:

  1. 如果存在分区P,那么系统需要选择A或者C,跟CAP一样;

  2. 否则Else,选择延迟Latency或是C // 要么延迟低 && 无法保证强一致性,要么延迟高 && 保证强一致。

▐ 3.1 只有分区出现时,才需要抉择A和C

用两个案例来说明CP和AP的场景

**【历史工单案例】**商家ERP调用仓储发货接口,某次发货请求调用超时后被统一封装成了调用失败的错误码,但实际仓储成功作业后出库。上游ERP看到失败后重新发起对菜鸟仓储的推单请求,导致重复发货资损。

这个案例中,调用请求超时让商家ERP和菜鸟仓储系统形成了两个「网络分区」,双方的状态都处于一个不确定态;在这个案例中,菜鸟的系统选择了可用性A,显式地告诉商家ERP确定性的结果,结果就是放弃了一致性C,数据不一致导致重复发货资损。

在这种场景更好的做法是选择一致性C,放弃可用性A。也就是说,如果没有办法保证一致性,宁可不可用。毕竟跟重复发货导致的资损相比,单笔请求不可用的危害小多了。不可用之后可以由系统规则或人工做兜底的检查,最终实现一致性。

**【架构设计案例】**菜鸟快递员使用揽件app上门揽件,为了不阻塞快递员的操作,在弱网或者离线环境下,允许快递员先使用app完成揽收操作,等网络状况恢复后再进行数据同步。

这种在弱网或没有网络的场景下,手机端的app和云端的server形成了两个分区。这里明显是选择了可用性A,而短暂地放弃了数据的一致性C。从这里也能发现,CAP定理还有一点没有讲,那就是当分区不存在之后,恢复数据一致性需要基于业务场景提前设计策略。

▐ 3.2 没有分区问题时,需要考虑L和C

A high availability requirement implies that the system must replicate data. As soon as a distributed system replicates data, a trade-off between consistency and latency arises.

高可用性要求意味着,系统必须复制数据。一旦分布式系统复制了数据,就会出现一致性和延迟之间的权衡。

**【架构设计案例】**菜鸟某业务作为物流行业的基础设施,在N年前实现了异地双活架构,要求在各数据节点保持强一致同步,折中接受了跨城写的延迟。

**【架构设计案例】**以下是两个例子说明了在没有分区存在时,选择延迟(Latency)而放弃一致性(Consistency)的场景:

  • 实时多人在线编辑文档(如 Google Docs):当多个用户同时编辑同一个文档时,为了提供流畅的用户体验,系统可能会允许短暂的不一致性(比如,不同用户看到的内容稍有差异)。一旦用户的编辑被提交,系统会尝试合并这些更改。
  • 社交媒体的时间线或信息流(如 Twitter 或 微博):当用户发布新的动态或图片时,为了快速响应,这些更新可能不会立刻对所有用户可见。系统可能会选择首先将这些更新存储在某些节点上,而其他节点稍后再获取这些更新。这意味着,在某个短暂的时间内,不同的用户可能看到的信息流是不同的。

4. PACELC对我们的启发

对于程序员或架构师来说,掌握PACELC协议不仅是体现了对分布式系统设计原理的深刻理解,更重要的是可以指导系统设计。由于CAP和PACELC定理已经被证明是存在的,我们在实际工程实践中,针对于一致性(Consistency)、可用性(Availability)、分区容忍性(Partition Tolerance)和延迟(Latency)需要做一些折中和权衡。

在云原生架构下,分布式系统面临着更复杂的网络及运行环境,网络分区、节点故障等异常已经是“常态”或者“共识”。如何在网络异常或延迟的情况下,保障业务系统的稳定性与健壮性,是每一位开发者不得不面对的问题。希望本篇文章可以对开发者有所启发,让每位同学都能用通过健壮的代码为用户提供稳定、高效和可靠的服务。

▐ 延伸阅读

[01]. CAP Twelve Years Later: How the “Rules” Have Changed

https://www.infoq.com/articles/cap-twelve-years-later-how-the-rules-have-changed/

END

阅读更多好文