分布式架构入门:一文轻松搞懂晦涩的CAP理论!

对于设计分布式系统的架构师来说, CAP 是必须掌握的理论。

CAP 定理( CAP theorem )又被称作布鲁尔定理( Brewer’s theorem),由加州大学伯克利分校(计算机领域神一样的大学)的计算机科学家埃里克·布鲁尔在 2000 年的 ACM PODC 上提出的一个猜想。2002 年,麻省理工学院(另一所计算机领域神一样的大学〉的赛斯·吉尔伯特和南希 ·林奇发表了布鲁尔猜想的证明 , 使之成为分布式计算领域公认的一个定理。

在我刚接触大数据平台的时候,第一次听到了CAP的理论,然后公司的架构师说hadoop属于CP系统(Consistency and Partition tolerance),不明觉厉。后来虽然我大致知道了CAP是什么意思,但也是一知半解,比如我并不清楚CAP的适用范围是什么,系统、数据还是应用?

最近看到了李云华的一本书:《从零开始学架构》,再一次接触到了CAP理论,这本书对于CAP的诠释还是比较通俗易懂的,在这本书的帮助下,再加上有ChatGPT的加持,自己终于对CAP理论有了全新的认识,现在再去理解分布式架构就有一览众山小的感觉,在此把我的领悟分享给大家。

一、CAP理论的缘起

在分布式系统的设计重点需要解决两个问题:横向扩展和高可用性,横向扩展是为了解决单点性能瓶颈问题,从而保证可用性,高可用是为了解决单点故障问题,进而保障部分节点故障时的可用性,由此可以看到,分布式系统的核心诉求就是可用性。这个可用性正是CAP中的A;用户访问系统时,可以在合理的时间内得到合理的响应。

为了保证可用性,一个分布式系统通常由多个节点组成,这些节点各自维护一份数据,但是不管用户访问哪个节点,原则上都应该读取到相同的数据。为了达到这个效果,一个节点收到写入请求更新自己的数据后,必须将数据同步到其他节点,以保证各个节点的数据一致性,这个一致性正是CAP中的C:用户访问系统时,可以读取到最近写入的数据。

分布式系统中,节点之间数据的同步是基于网络的,由于网络本身的不可靠性,极端情况下会出现网络不可用,从而将网络两端的节点孤立开来,这就是网络分区的现象。发生网络分区时,系统中多个节点数据一定是不一致的,但可以选择对用户表现出一致性,代价是牺牲可用性,将未能同步到新数据的部分节点设置为不可用,当然也可以选择可用性,此时系统中各个节点都是可用的,只是返回给用户的数据不一致,这里的选择,就是CAP中的P。

以上就是CAP理论的背景,大家可以知其所以然。

二、CAP定义的辨析

有比较才有鉴别,CAP理论的定义有很多版本,通过比对这些版本的差异,让我对CAP有了更深入的理解,这里挑选了了2个典型版本:

版本1:

对于一个分布式计算系统,不可能同时满足一致性( Consistence)、可用性(Availability)、分区容错性( Partition Tolerance)三个设计约束。

一致性(Consistence):所有节点在同一时刻都能看到相同的数据。

可用性(Availability):每个请求都能得到成功或失败的响应。

分区容错性( Partition Tolerance):尽管出现消息丢失或分区错误,但系统能够继续运行。

版本2:

在一个分布式系统 (指互相连接并共享数据的节点的集合)中,当涉及读写操作时,只能保证一致性( Consistence)、可用性( Availability)、分区容错性( Partition Tolerance)三者中的两个,另外一个必须被牺牲。

一致性(Consistence):对某个指定的客户端来说,读操作保证能够返回最新的写操作结果(A read is guaranteed to return the most recent write for a given client)。

可用性(Availability):非故障的节点在合理的时间内返回合理的响应 (不是错误和超时的响应)。

分区容错性( Partition Tolerance):当出现网络分区后,系统能够继续 “履行职责”。

我们来具体看看两者的差异:

1、第二版强调了CAP 理论适用于哪种类型的分布式系统,第一,互相连接并共享数据的节点的集合,第二,关注的是对数据的读写操作,而不是分布式系统的所有功能。

2、在一致性上,第一版从节点 node 的角度描述,第二版从客户端 client 的角度描述。第一版强调同一时刻拥有相同数据,第二版并没有强调这点 。这就意味着实际上对于节点来说,可能同一时刻拥有不同数据,这和我们通常理解的一致性是有差异的。

3、在可用性上,第一版的“每个请求都能得到成功或失败的响应”定义比较模糊,因为无论是否符合CAP理论,我们都可以说请求成功和失败,因为超时也算失败,错误也算失败,异常也算失败,结果不正确也算失败;即使是成功的响应,也不一定是正确的。例如,本来应该返回100,但实际上返回了90,这就是成功的响应,但并没有得到正确的结果。相比之下,第二版的解释明确了不能超时,不能出错,结果是合理的,注意没有说“正确”的结果。例如,应该返回100但实际上返回了90,肯定是不正确的结果,但可以是一个合理的结果。

4、在分区容错性上,第一版用的是“继续运行”,第二版用的是“履行职责”。只要系统不宕机,我们都可以说系统在运行,返回错误和拒绝服务都是运行,而“履行职责”表明发挥正常作用,这点和可用性是一脉相承的,相比之下更加明确。

三、CAP潜在的约束

理论的优点在于清晰简洁,易于理解,但缺点就是高度抽象化,省略了很多细节,导致在将理论应用到实践时,由于各种复杂情况,可能出现误解和偏差, CAP 理论也不例外。

1、CAP有适用范围

正如定义中所说,CAP是有适用范围的,乱套用CAP往往谬以千里。

这里以一个电商网站订单模块的下单、付款、扣减库存操作为例说明。在超时的情况下,订单数据和库存数据状态会不一致,这属不属于CAP理论的适用范围呢?答案是不适用。

大家不要一看到不一致就认为适用CAP理论。前面已经讲过,CAP的适用范围只是针对共享、互联的数据,订单和库存系统虽然是互联的,但没有共享的数据,超时情况下产生的不一致只能靠对账和人工修复等方式解决。但如果针对的是各节点的库存数据的一致性,则适用CAP理论,比如当用户下单支付后,各节点的库存数据需要立即更新,以保证所有查看该商品的用户都能看到最新的库存信息。

2、CAP理论中,P是必选项

虽然 CAP 理论定义是三个要素中只能取两个,但放到分布式环境下来思考,我们会发现必须选择 p (分区容忍)要素,因为网络本身无法做到 100%可靠,有可能出故障,所以分区是一个必然的现象。如果我们选择了 CA 而放弃了 P,那么当发生分区现象时,为了保证 C,系统需要禁止写入,当有写入请求时,系统返回 error (例如,当前系统不允许写入),这又和 A 冲突了 ,因为 A 要求返回 no error 和 no timeout。因此,分布式系统理论上不可能选择 CA 架构 ,只能选择 CP 或 AP 架构。

3、CAP关注的粒度是数据, 而不是整个系统

CAP 理论的定义和解释中,用的都是 system、 node 这类系统级的概念,这就给很多人造成了很大的误导,认为我们在进行架构设计时,整个系统要么选择 CP,要么选择 AP。但在实际设计过程中,每个系统不可能只处理一种数据,而是包含多种类型的数据,有的数据必须选择CP,有的数据必须选择 AP。而如果我们做设计时,从整个系统的角度去选择CP还是AP,就会发现顾此失彼,无论怎么做都是有问题的。

一个电商网站核心模块包括会员,订单,商品,支付,促销管理等等,不同的模块数据特点不同,因此适用不同的CAP架构。

会员模块包括登录,个人设置,个人订单,购物车,收藏夹等功能,这些模块只要保证AP,即对用户的及时响应,数据短时间不一致不大会影响使用。订单模块的下单付款扣减库存操作是整个系统的核心,CA都需要保证,在极端情况下牺牲P是可以的。商品模块的商品上下架保证CP即可,因为后端操作可以允许一定的时延;促销模块短时间的数据不一致,结果就是优惠信息看不到,但是已有的优惠保证可用,所以保证AP也可以。

现在大部分电商网站对于支付是独立的系统,C是必须要保证的,AP中A相对更重要,不能因为分区导致所有人都不能支付。

4、CAP是忽略网络延迟的

这是一个非常隐含的假设,布鲁尔在定义一致性时,并没有将延迟考虑进去。也就是说,当事务提交时,数据能够瞬间复制到所有节点。但实际情况下,从节点 A 复制数据到节点 B,总是需要花费一定时间的。这就意味着, CAP理论中的 C 在实践中是不可能完美实现的,在数据复制的过程中,节点 A 和节点 B 的数据并不一致。对于严苛的业务场景。

例如和金钱相关的用户余额、和抢购相关的商品库存,技术上是无法做到分布式场景下完美的一致性的。而业务上必须要求一致性,因此单个用户的余额、单个商品的库存,理论上要求选择 CP 而实际上 CP都做不到,只能选择 CA。也就是说,只能单点写入,其他节点做备份,无法做到分布式情况下多点写入,这是符合实际情况的。

5、CAP的AP和CP不是绝对的

CAP理论告诉我们三者只能取两个,需要牺牲另外一个,这里的牺牲有一定误导作用,因为牺牲让很多人理解成什么都不做,实际上,CAP理论的牺牲只是说分区过程无法保证C或者A,但不意味着什么都不做,因为在系统整个运行周期中,大部分时间都是正常的,发生分区现象的时间并不长,分区期间放弃C或A,并不意味着永远放弃,可以在分区期间进行一些操作,比如记录日志,从而让分区故障解决后,系统能够重新达到CA的状态。

比如用户账号数据,假设选择了CP,则分区发生后,节点1可以继续注册新用户,节点2无法注册新用户,此时节点1可以记录新增日志,当分区恢复后,节点2读取节点1的日志就可以让节点1和节点2同时满足CA的状态。

6、CAP的可用性与高可用有区别

HBASE、MongoDB属于CP架构,Cassandra、CounchDB属于AP系统,但我们能说后者比前者更高可用么?应该不是。CAP中的高可用,是指在某一次读操作中,即使发现不一致,也要返回响应,即在合理时间返回合理响应。我们常说的高可用,是指部分实例挂了,能自动摘除,并由其它实例继续提供服务,关键是冗余。

7、CAP的网络分区有明确定义

网络故障、节点应用出现问题导致超时,属于网络分区,节点宕机或硬件故障,则不属于。因此如果有人说机器挂了怎么样,这种情况不属于CAP理论适用的范围,CAP关注的是分区时的可用性和一致性,不是说保证整个集群不挂。

四、BASE是CAP的补偿

为了解决CAP限制,出现了BASE理论,也就是基本可用(Basically Available)、软状态(Soft state)、最终一致性(Eventually Consistent)理论。BASE是对CAP中一致性和可用性权衡的结果,其通过牺牲强一致性来获取高可用性。

1、基本可用(Basically Available):指的是分布式系统在出现故障的情况下,仍然可以提供服务,尽管这个服务可能不完全,或者有降级,这里的关键是部分和核心。

以电商网站为例,假设一个电商网站有订单服务、商品浏览服务、评论服务、搜索服务等多个服务。如果因为某种原因(如网络分区、硬件故障等)导致评论服务暂时不可用,但是其他服务,如订单服务、商品浏览服务、搜索服务等仍然可用。此时,用户仍然可以浏览商品、下订单和搜索,只是不能进行评论。也就是说,整个系统仍然是"基本可用"的。

2、软状态(Soft state):允许系统中的数据存在一段时间的不一致。

例如,当你第一次访问一个网站的时候,你的计算机会向DNS服务器查询这个网站对应的IP地址,然后DNS服务器会返回IP地址,这个IP地址会被你的计算机或者你的网络设备缓存起来,以备下次访问的时候使用,以节省查询时间。但是,如果在这个缓存期间,网站服务器更换了IP地址,那么你的计算机或者网络设备缓存的DNS解析结果就会过期,这就是一个"软状态"。

3、最终一致性(Eventually Consistent):系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。这里的关键词是“一定时间”和“最终“,“一定时间”和数据的特性是强关联的,不同的数据能够容忍的不一致时间是不同的。

例如,在一个社交媒体网站上,当用户发布一条新的状态更新或者照片,他的朋友们可能不能立刻看到这个更新。这是因为这个新的状态更新需要被复制到数据中心的各个节点,这个过程可能需要一些时间。在这个场景中,用户通常能接受这种延迟,因此对于最终一致性的时间容忍度相对较大。但是,当用户在电商网站购买商品时,库存数据的对最终一致性的时间容忍度相对较小,因此,电商网站需要尽快地更新和传播库存变化,以确保所有的用户都能看到准确的库存信息。

前面讲过,完美的CP是不存在的,即使是几毫秒的数据复制延迟,在这几毫秒的时间间隔内,系统是不符合CP要求的,因此,CAP中的CP方案,实际上也是实现了最终一致性。AP方案中牺牲一致性,则只是在分区期间,而不是永远放弃一致性,在分区故障恢复后,系统应该达到最终一致性,因此,BASE是CAP理论的延伸。

五、CAP和ACID的辨析

CAP中的一致性有时会和ACID的一致性产生概念混淆,那么ACID的C到底跟CAP的C有什么区别呢?

ACID是指数据库事务正确执行的四个基本特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。在这里,一致性的定义是:数据库的状态应该从一个一致的状态转移到另一个一致的状态,即事务执行前后都保持业务规则的一致性,如完整性约束等。

两者的主要区别在于其应用的范围和关注点不同:

1、CAP中的一致性更多的是从分布式系统的角度考虑,关注的是分布式节点间的数据一致性问题,即所有节点看到的数据是否实时一致。

2、ACID中的一致性是从单个数据库系统的角度考虑,主要关注的是数据库在进行事务操作后,数据是否满足预定义的业务规则和约束,保证数据的正确性。

举个具体的例子来说明:

假设你有一个银行应用程序,这个程序有一个简单的业务规则:客户的账户余额不能小于0。在这个场景下,如果一个客户想要从他们的账户中提取500美元,系统会首先检查账户余额是否满足这个要求。如果账户余额是600美元,那么提取操作是可以进行的,并且完成后,账户余额将是100美元。这是一个一致性状态,因为它满足了业务规则。

现在,假设在这个事务中,提取操作已经完成,但是在更新余额时,系统突然崩溃了。在这种情况下,系统应该能够恢复并且完成余额更新,或者它应该完全忽略这个事务,就好像它从未发生过一样。在任何情况下,客户的账户余额都不应该被错误地减少,因为那将违反业务规则。

所以,ACID的一致性是关于在事务开始和结束时满足特定业务规则和约束的,无论事务过程中是否发生了错误或者系统崩溃,数据库都应始终保持一致性状态。

六、CAP的应用案例

1、ZooKeeper

ZooKeeper(ZK)是一个分布式的、开放源码的分布式应用程序协调服务,由雅虎公司开发,并是Apache项目的一部分。ZooKeeper是一种典型的CP(Consistency/一致性, Partition tolerance/分区容错性)系统。

ZooKeeper的设计就是这样的。当网络发生分裂,只有数量大于半数的节点(称为“过半机制”)可以继续提供服务,能够保证数据的一致性。数量少于半数的节点会拒绝服务,以此来保证整个系统的一致性。这意味着在部分节点不可用或者网络分区的情况下,ZooKeeper可能无法保证所有客户端的可用性。

ZooKeeper主要被用于管理和协调分布式系统中的状态信息,如配置信息,状态同步,命名服务和分布式锁等。数据的一致性在这些用途中是非常关键的,因此ZooKeeper选择了牺牲一部分可用性以保证一致性。

2、Kafka

CAP定理告诉我们,在网络分区的情况下,不可能同时保证一致性(Consistency)和可用(Availability) 。但这并不意味着我们不能在一致性和可用性之间找到适合自己的平衡点。

在Kafka中,例如,我们可以通过设置不同的"acks"(acknowledgements)和"min.insync.replicas"参数来权衡一致性和可用性。如果我们设置"acks"为"all"或者"-1",并且将"min.insync.replicas"设置为一个大于1的数,那么我们就可以提高数据的一致性,但可能会降低系统的可用性,因为每次写操作都需要等待所有的副本都确认。

反之,如果我们设置"acks"为"1",那么写操作只需要等待一个副本的确认,这就提高了系统的可用性,但可能降低数据的一致性,因为其他的副本可能还没有完成数据的更新。

3、HBase

HBase的设计目标是提供高速的读写访问大量数据,并保证强一致性。在HBase中,数据是自动分片的,每个分片(称为region)由一个RegionServer来服务,每个行键只由一个RegionServer来服务,所以对单个行的读写都是强一致的。

当网络分区发生时,HBase通常会选择牺牲部分可用性以保持一致性和分区容错性。比如说,如果一个RegionServer出现问题,HBase的主节点(HMaster)会将它上面的regions重新分配给其他健康的RegionServers,这个过程中涉及的regions会在短时间内不可用,因此,HBASE属于CP系统。

4、Redis

Redis是一个开源的键值存储系统,它通常用于作为数据库、缓存和消息代理。Redis单实例是一个基于内存的数据结构存储,并提供持久化机制。对于单实例的Redis,CAP理论并不适用,因为它并不是一个分布式系统。

在Redis的主从复制模式中,如果主节点故障,系统需要手动干预才能恢复写服务(即升级一个从节点为新的主节点)。这意味着它不能自动处理网络分区,因此在严格意义上,它也不能被归类为CAP理论中的任何一类。

对于Redis Cluster,它是一个分布式的Redis解决方案,能够在一定程度上处理网络分区的问题。在出现网络分区时,Redis Cluster会停止对分区节点的操作以保持数据的一致性,所以它更倾向于CP系统。

5、Cassandra

Apache Cassandra是一个开源的分布式NoSQL数据库,它是为了满足高可用性和扩展性的需求而设计的。

Cassandra使用了一种名为最终一致性(Eventual Consistency)的模型。在这个模型中,系统不保证在任何时刻所有的副本都是一致的,但保证在没有新的更新操作的情况下,所有的副本最终会达到一致的状态。

具体来说,当一个写操作发生时,Cassandra只需要一部分(可以配置)副本确认就可以认为写操作成功了。这样可以提高系统的可用性和写入性能。然而,这也意味着在某些情况下,读操作可能会返回过时的数据,因为不一致的副本可能还没有被更新。

所以,Cassandra是一个典型的AP系统。然而,通过调整配置,例如设置更严格的一致性级别,可以使Cassandra在一定程度上提供更强的一致性保证。

希望对你有所启示。

e0eeec956b425d7968344b5bd142f767.png

3b6fea86aa78025e255b2f68eb40d676.png

7184c04e567896d86abc65fba5b76b41.png

bc6776bf621832748c9b5014b6d23ad8.png

阿里云数据中台数据模型-系列白皮书

为中台正名 | 数字化转型真谛是连接和开放,没中台和API还真不行

阿里宣布史上最大调整:加强敏捷,做薄中台,“大中台” 将何去何从?

中台战略

数据仓库与数据治理思维导图.xmind(全)

6000字长文,终于将数据中台架构体系讲明白了

一个具体场景剖析业务中台和数据中台的关系

查看全部文章

点击左下角“阅读原文”查看更多精彩文章,公众号推送规则变了,如果您想及时收到推送,麻烦右下角点个在看或者把本号置顶

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
分布式数据库原理是指将数据分散存储在不同的物理节点上,通过网络进行通信和数据同步的数据库系统。它可以提高数据库的可扩展性、容错性和性能。 分布式数据库的设计思想是将数据划分为多个分片,每个分片存储在不同的节点上。通过数据划分,可以将数据存储在离用户更近的节点上,提高数据的访问速度。同时,分布式数据库可以通过数据复制和数据分发来提供容错性。数据复制可以将数据备份到多个节点上,当某个节点发生故障时,系统可以自动切换到其他节点上继续提供服务。数据分发可以将请求分发到不同的节点进行处理,提高系统的并发处理能力。 PostgreSQL是一种开源的关系型数据库管理系统,具备分布式架构。PostgreSQL的分布式架构包括一个主节点和多个从节点。主节点负责接收用户的请求,并将数据同步到从节点上。从节点可以进行读操作,提高系统的并发处理能力。如果主节点发生故障,从节点可以自动切换为主节点,保证系统的可用性。 PostgreSQL的分布式架构基于流复制技术。主节点将产生的日志记录(WAL日志)通过流复制传输到从节点,从节点会将这些日志记录应用到自己的数据库中。这样可以确保主节点和从节点之间的数据一致。同时,PostgreSQL还支持逻辑复制和扩展查询,可以根据实际需求对数据进行同步和查询的优化。 总之,分布式数据库原理是通过数据的划分、复制和分发,提高数据库的可扩展性、容错性和性能。PostgreSQL的分布式架构基于流复制技术,通过多个节点的协作来提供可靠的数据存储和高效的数据访问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

傅一平

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值