深入浅出 -- 系统架构之分布式CAP理论和BASE理论

这篇具有很好参考价值的文章主要介绍了深入浅出 -- 系统架构之分布式CAP理论和BASE理论。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

科技进步离不开理论支撑,而当下大行其道的分布式架构,透过繁荣昌盛表象,底层同样离不开诸多分布式理论撑持。当然,相信诸位在学习分布式相关技术时,必然学到过两个分布式领域中的基础理论,即:CAP与BASE理论

一、分布式基础 - CAP理论

分布式事务 cap base理论,系统架构,分布式

当一个从逻辑上被视为整体的系统,拆散到多个节点部署时,则能称之为分布式系统,分布式领域中的CAP理论,即是图中三个单词的首字母缩写组合,CAP由三个指标组成:

  • CConsistency(一致性);
  • AAvailability(可用性);
  • PPartition tolerance(分区容错性)。

2.1、Consistency一致性

分布式和以往集中式部署的单体架构不同,它可以部署在多个节点上,以Redis为例,如果只部署一个节点,则属于单机版本,采用主从、分片等集群模式部署,称之为分布式版本。所谓的一致性,即是在同一个分布式系统中,同一时刻的所有节点,能看到的数据完全相同

分布式事务 cap base理论,系统架构,分布式

比如2024-03-10 11:11:11这个时间点,两个读取相同Key的请求,一个落入到主节点A,另一个落入到从节点B,读到的数据必须完全相同,这保证了数据的完整性和准确性。反之,如果这两个请求拿到的结果不同,意味着Redis主从集群这个分布式系统中,并没有实现数据一致性。

PS:同时,一致性还要求:一旦某个数据在分布式系统中的某个节点上被更新(如修改成新值),那么后续对该数据的读取操作,无论发生在哪个节点上,都应该返回更新后的值,即:所有节点在同一时间内,都能看到相同、且最新写入的值

基于上述结论来问个问题:在MySQL主从模式下,一个新值写入后还未提交,此时在从节点上读取到了老值,满足CAP的一致性要求吗?

答案是满足,只要保证事务提交前,所有节点读到的数据都为老值,就满足一致性要求!因为带事务性质的场景中,写入动作的完成时机,并不是数据落到某个节点,而是整个事务被提交时,只有当事务被提交,才代表真正完成了数据写入。

2.2、Availability可用性

分布式系统因为部署在多个节点,虽然避免了单点故障问题,但也会增加整个系统的风险出错率,还是上面Redis的例子,A、B、C三个节点都有可能出现故障。而CAP里的可用性,即是指分布式系统中,能够始终对请求做出响应,好比B节点发生错误,整个Redis服务依旧要能够正常处理并响应外部的请求,不能由于某一个或部分节点的损坏,导致整个系统陷入不可用状态。

可用性强调的是系统对外部请求的响应能力,具体来说,它要求系统能够在一定的时间内,对任何非失败的外部请求做出响应。这意味着,无论系统内部发生什么情况,只要外部用户发出请求,系统都应该尽快做出响应,即使回应的是拒绝服务或错误消息。因此,可用性关注的是系统对外部请求的响应速度和可靠性。

2.3、Partition tolerance分区容错性

组成分布式系统的多个节点,可以部署在任意节点上,这意味着我们可以用物理位置不同的服务器来部署系统,不同节点间的协调与数据同步,都依靠网络来完成。当组成分布式系统的多个节点,其中某个节点出现网络故障时(如网络中断、抖动、网络设备损坏等),对系统内其余正常的节点来说,无法通过网络感知到该节点,它成为无法通信的孤立区域,从而造成了网络分区。

PS:CAP里的网络分区,并非是网络编程里的局域网概念,而是指分布式系统内部,网络出现故障时,系统中的节点可能被分割成多个独立的子网络,这些子网络之间的通信被阻断,导致数据无法在它们之间自由流动。

CAP里的P分区容错性,就要求系统在这样的情况下仍然能够正常运行,即使系统内出现了多个分区,分布式系统依旧能正常运行,并对外提供基本的服务(至少一部分服务可用)。当然,某个节点掉线会造成孤立区域出现,系统内动态加入节点,同样也会导致分区问题。

透过表象看本质,因为新节点加入和老节点离开,都可以视为系统内部的网络分区,CAP里的分区容错性,本质就是分布式系统对节点动态加入和离开的处理能力!

2.4、CAP三者选其二问题

上面对CAP理论做了展开,讲清了其中的三个指标,简单总结下:

  • 一致性要求所有节点在同一时间看到相同的数据;
  • 可用性则要求系统能够始终对请求做出响应;
  • 分区容错性则是指系统在遇到网络分区时,仍然能够保持一定的可用性和一致性。

虽然其中的A、P在某些方面看起来相似,但它们关注的焦点并不相同,可用性侧重于系统对用户请求的响应能力,而分区容错性则更侧重于系统在出现网络分区时的表现,这里请大家一定要区分清楚。

好了,相信大家一定听过一句定理:CAP三个指标不可能同时做到,三者只能选其二,意味着只能有CA、AP、CP三个组合,但大家仔细想想,你听说过市面上有保证CA的分布式组件吗?肯定没有,Why

换个角度来看待上面提出的问题,假设我们自己要研发一款分布式组件,如果要保证CA(一致性与可用性),该怎么实现?

可用性可以理解成高可用,高可用的前提是解决单点故障,因此我们可以考虑集群设计方案,使用多个节点来组成整个系统,当系统部分节点出现故障时,外部请求能自动转移到其他健康的节点上处理。通过这种方案,我们可以保证系统在节点故障时的可用性,不过这里又有个问题,如何感知节点是否健康?

设计健康检查机制!而最主流的方案则是心跳机制,就好比一个正常的人,一定会有心跳,换到程序设计中,一个正常的节点,必然也具备发送心跳包的能力。反之,如果一个节点发送不了心跳包,或者系统内其他节点收不到某个节点的心跳包,说明该节点已经处于故障状态,后续不用将请求转发到该节点。

保障了可用性后,接着来看看一致性,因为此时有多个节点,多个节点的数据一致该怎么实现?选择2PC、3PC这类强一致方案,当外部往某个节点写入数据时,该节点触发数据同步机制,将写入的数据同步给所有节点,当所有都同步完成后,再给客户端返回写入成功,这样就能保证所有节点数据完全一致。

通过上述步骤,就设计出了一个简易版的CA分布式组件,存在什么问题吗?问题很大,节点间的心跳检测、数据同步,需要依靠网络进行通信,先来看看心跳检测的问题:

①某个节点其实很健康,但发出的心跳包,因为网络抖动造成丢包,其他节点没收到就认为它故障了,这合理吗?不合理。
②某个节点发出的心跳包,部分节点收到了,部分节点没收到,一部分节点认为健康,一部分节点认为故障,从而造成了分区,怎么办?

再来看看保证一致性的数据同步方案,假设某个节点故障,又或者同步数据时的包丢失,导致系统内多个节点数据不一致,系统为了达成“数据一致态”,会不断触发重试机制,造成外部请求阻塞,一直无法成功写入……

综上,最开始的设计思路,只是我们最理想的状态,但网络其实是个不可控因素,总会由于各种各样的原因造成故障出现。因此,在设计分布式系统时,网络故障带来的分区问题,一定要率先考虑,如果对分区问题没有容错性,代表系统内一个节点出现问题时,会造成整个系统无法正常运行,这也是为什么只有保证AP、CP的分布式组件,没有保证CA的原因。

PS:有没有能保证CA的组件呢?答案是有,就是单机版本,毕竟只有一个节点,数据写入成功后,就能保证多个外部请求看到的数据都相同;同样,只要这一个节点活着,系统就肯定可用,也是一种“狭义上的可用”。

综上,分布式肯定要保证P,无法保证P的分布式组件,只能被称为“部署在多个节点上的单体系统”,为此,对于CAP那幅图,正确的画法应该是这样的:

分布式事务 cap base理论,系统架构,分布式

虽然很多人在聊CAP时,说到三选二,可是分布式系统中,实际只能在A、C里选,不存在CA这个组合! 好了,回过头,再来看为什么CAP不能一起实现呢?

分布式系统中的通信离不开网络,而恰恰网络出现故障是常事,在出现分区问题时,节点间的通信会受到严重阻碍,来看个例子:

分布式事务 cap base理论,系统架构,分布式

如上图所示,该系统由A、B、C三个节点组成,其中由于C节点故障导致分区问题出现。如果要完全满足CAP里的一致性要求,意味着当外部写入数据时,A节点必须等到C节点同步完成,才能给客户端返回写入成功,可此时C节点已经挂了,注定着数据写不进去……

假设此时出现读取该数据的请求怎么办?此时只有两种办法:

  • ①放弃可用性:等待所有节点的数据都达到一致状态,保证任意节点返回的数据都相同,可这时系统必然无法及时响应;
  • ②放弃一致性:给客户端返回已经写入进A、B的新数据,但后续C节点恢复,请求去到C时,会出现读取到的数据不一致;

通过这个例子,相信大家一定明白了C、A之间为何只能选一个,保证可用性(AP),虽然可以快速响应外部请求,但无法做到任意时间点、所有节点数据的一致;保证一致性(CP),就需要等到所有节点数据达到一致,从而造成系统无法及时响应外部请求,可用性降低。

2.5、为何90%分布式系统无需实践CAP理论?

在一开始我就给了一个定论:90%以上的分布式系统,不需要实践CAP理论,下面展开聊聊。

前面给过分布式系统的定义:当一个从逻辑上被视为整体的系统,拆散到多个节点部署时,则能称之为分布式系统,而分布式系统也可以分为两类,一类是带存储性质的,另一类则是非存储性质的(类似于Kubernetes里的无状态Pod),而90%以上的开发者,负责开发的分布式系统都属于后者,啥意思?

包括我在内的大部分人,平时都在做业务开发,而一个业务性质的分布式系统,需要实践CAP理论吗?并不需要,因为业务系统本身只有逻辑处理,没有数据存储,自然不存在所谓的数据一致性(数据最终是存在各种组件里,如数据库)。真正需要实践CAP理论的分布式系统,主要是带存储性质的分布式系统,如Redis、MQ、数据库、注册中心……

CAP理论应用最广的“注册中心”领域为例,正是因为它需要存储服务注册的信息,所以才需要实践CAP理论,也只有在研发这类分布式组件时,才需要在一致性、可用性间做取舍。作为业务开发者,我们只需要站在已有组件上做考量,想清楚到底用CP,还是AP就足够了。

2.6、在业务中应用CAP思想

除开研发分布式存储组件要实践CAP理论外,做业务类型的分布式系统,哪些场景会用到CAP思想呢?下面举些例子说明。

通过传统的数据库,搭建多库架构(主从、多主)时,选择同步复制,说明更关注数据一致性(CP);选择异步复制,则代表更关注响应速度(AP),具体原因可参考《MySQL主从原理篇》。

使用分布式锁时,在Redis、Zookeeper都为主从集群模式的情况下,如果选择Redis来实现分布式锁,代表更关注响应速度(AP);如果选用ZK来实现,则代表更关注一致性(CP)。

微服务项目,选择服务注册中心时,……

通常而言,如果更关注性能,可以选择AP类型的组件,毕竟AP舍弃了数据一致性,只需等数据写入主节点,就可以向客户端返回写入成功,这无疑会大幅度提升请求的响应时间。但AP组件存在数据丢失的风险,比如数据刚写进主节点,还没来得及同步给从机,主节点就宕机了,此时切换上来的新主,就会丢失这部分数据。

反之,如果更关注数据安全性,则可选用CP类型的组件CP放弃了可用性,优先保证数据一致性,当数据写进主节点后,往往需要等到从节点也写入完成,最后才能给客户端返回写入成功,这显然会拖慢响应速度,因为从机未写入成功,请求则需要一直阻塞等待。不过这种模式有个好处,就是当主节点宕机时,无论是哪台从机成为新主,都能保证拥有最完整的数据,不会存在数据丢失现象。

最后,技术没有绝对的好坏,实际项目中究竟选什么类型的组件,不能随心而定,而是得先深度了解业务场景,再进行技术选型,不同的业务关注面并不一样。

二、分布式核心 - BASE理论

前面提到分布式系统不可完全满足CAP的三个指标,但完全舍弃一致性,或可用性也绝对不行,怎么办?

有些熟悉分布式理论的小伙伴,下意识会喊道:BASE理论,这个答案对吗?不一定对,虽然很多讲解CAP的资料,一提到CAP,自然而然就会扯上BASE理论,美名其曰:BASE理论可以让我们不必在A、C中做抉择,而是可以实现部分的A和C;又或者说:BASE理论是在CAP基础上,满足AP后对C方面的拓展与延申

你觉得上面这类说法正确吗?很多人都会觉得对,因为大部分人当初就是这么学的……

如果你对BASE理论也是上述两种理解,那……,或许你一直都未曾真正搞懂CAPBASE这两个分布式理论

当然,为了更好的“掰正大家的观念”,以及照顾分布式知识薄弱的小伙伴,我们先简单讲讲BASE理论。

分布式事务 cap base理论,系统架构,分布式

Basically Available、Soft state、Eventually consistent简称为BASE理论,该理论最早源于ACM上《Base: An Acid Alternative》这篇论文,由eBay系统架构师Dan Pritchett2008年发布,该理论提出了三个概念:

  • BABasically Available(基本可用);
  • SSoft state(软状态);
  • EEventually consistent(最终一致性);

为了后面更好的讲述CAPBASE理论之间的关系,我们先快速认识/回顾一下上面这三个概念。

2.1、Basically Available基本可用

基本可用这个概念很好理解,比如咱们买了一台“船新版的遥遥领先”,因为是新机,所以功能、硬件、系统都没问题,属于“完全可用状态”。

众所周知,“遥遥领先”不算便宜,小竹这个人呢,比较好面子,也想要一台,可是买不起怎么办?正巧此时小竹的好朋友:大熊猫,昨天刚到的全新版,不小心从十八楼摔下去了,于是想换台新的。小竹听闻此事后,眼珠一转、双手一拍,怒斥千元巨资!全款!不分期!将其成功拿下!

拿到手后,虽说这屏幕有点稀碎、按键有点松、机身有点歪……,但好歹开机还能亮啊!毕竟有句话说得好: 又不是不能用

好了,到此时,小竹手里这台“战损版-遥遥领先”,尽管卖相不咋滴,但功能方面基本没问题,凑合凑合也成,这就属于“基本可用状态”。

换成分布式领域亦是同理,当系统出现故障或意外情况时,允许降低部分可用性,保证系统基本可用,而这类情景十分常见,比如大促活动期间:

  • 熔断/限流:当系统负载达到指定阈值时,新到来的请求会被拒绝(返回配置好的提示语);
  • 关闭非核心业务:如禁止大数据报表导出、停掉部分非关键性的任务,给核心业务腾出资源;
  • 服务降级……

基本可用的核心思想就是:当系统出现故障或意外情况时,允许放弃掉部分可用性,保证核心功能可用,或能响应外部请求(返回自定义的错误提示也可以)即可

PS:基本可用不是“不可用”,就好比一台遥遥领先,已经摔成了十八瓣,还能算基本可用吗?当然不行……

2.2、Soft state软状态

软状态在有些地方也叫弱状态,是指允许系统存在中间状态,并且该中间状态不会影响系统整体的可用性

这就好比传统关系型数据库里的事务机制,假设没有事务机制,写入数据就只有成功、失败两种状态:

  • 成功:数据成功保存到数据库,当出现读取请求时,能正常读到写入(或更新)后的值;
  • 失败:数据未保存到数据库,当出现读取请求时,只能看到之前的值,或看不到值;

而有了事务机制后,在成功与失败之间,多了一个中间态,即:数据写入成功,事务暂未提交,这个中间态的存在,也不会影响数据库整体的可用性。

2.3、Eventually consistent最终一致性

BASE理论中,最终一致性是和软状态绑定的,两者需要结合在一起理解。前面说到,软状态允许系统内存在中间态,但要记住:如果这个中间态,一直不变成终态,而是卡在那里的话,就会影响系统整体的可用性

啥意思?结合上面给出的数据库事务例子来说,如果一个事务处于中间态(写入成功,但一直不提交);当其他请求继续对该事务操作的数据行进行更新时,就会被阻塞,从而影响了系统的可用性,这就违背了“软状态”的定义。

软状态除开强调允许存在中间态外,还声明了该中间态不会影响系统整体的可用性,意味着这个中间态,注定只能短暂存在,在一定时间后,肯定会变成终态

BASE理论里的最终一致性,就是为了填补“卡在中间态不变化”这个逻辑漏洞,代表系统内出现中间态时,经过一定时间推移后,最终肯定能达到一致的状态(终态)。当然,这样讲或许有点难理解,来套入一个常见的分布式场景:

分布式系统中,有个落地页渲染所需的数据比较复杂(如数据看板),得调用多个服务的接口进行组装才能返回,这个过程非常耗时,可能需要几分钟之久。

面对这种情况一般会怎么做?通常会提前聚合好数据,而后放入到RedisES中进行缓存,以便后续能快速拿到渲染所需的数据。

问题来了,现在参与聚合的一部分数据更新了,那提前聚合出的结果就会不一致,怎么办?先来看看现在的终态:

  • ①参与聚合的基础数据更新成功,聚合结果实时更新;
  • ②参与聚合的基础数据更新失败,聚合结果保持不变。

之前仅有这两个终态,如果要进行满足状态,既耗费资源,又会响应缓慢,为此就可以允许中间态存在,保证最终一致性即可(如开启定时任务,定时聚合并刷新缓存中的数据)。

总之,只要参与聚合的基础数据不再更新,随着时间推移,定时任务肯定会把缓存中的结果,刷新成“最新的基础数据聚合后的结果”,让系统内的数据达到一致状态,这就是最终一致性!

三、固有认知的拨乱反正

上节简单讲了下BASE理论的定义,接下来回到一开始的问题:为什么我说BASE理论和CAP理论没太大关系?

想要讲明白这个问题,我们得重新认识下CAP理论,CAP理论更偏向于分布式存储这个领域,而且并非所有分布式存储领域都会用到CAP,只有哪些存在数据副本的分布式存储场景,如所谓的主从集群、多主集群、镜像集群、复制集群、副本集群……等场景时,才会用到CAP,因为这些情况下才会涉及到数据同步,才会涉及到数据一致性问题!

而分库分表、Redis-Cluster、MongoDB-Cluster……这类分片式存储的场景中,尽管也都是分布式存储场景,可由于每个节点存储的数据本来就不同,自然不存在所谓的数据一致性问题,也就自然不存在所谓的CAP实践,这点希望大家一定要弄清楚,否则说明你并未真正理解CAP思想。

PS:CAP理论最早是在1998年由Eric Brewer提出,这是26年前的事了,当时分布式领域最前沿的技术,就是主从集群这一块,因此该理论更多针对的是这个方向。

回到一开始讲的CAP一致性,其定义是:所有节点在同一时间内,都能看到相同、且最新写入的值,注意看“所有节点看到相同值”这句话,什么情况下,所有节点的数据才需要相同?即上面提到的“数据副本”场景。也就是说,CAP理论里的一致性,关注点是:副本节点数据同步间的一致性

再回头来看BASE理论里面的最终一致性,这里的一致性和CAP里的一致性,两者是一回事吗?并不是,BASE里的一致性维度更高,关注点是:分布式系统里的状态一致性,即中间态最终会演变成终态(不理解没关系,后续会举例展开)

既然BASE并非CAP的延申理论,那它究竟是个啥?我相信绝大多数小伙伴,并没有认真看过ACM平台上那篇BASE论文,我带大家来仔细看,其中有一段是这样的:

分布式事务 cap base理论,系统架构,分布式

看图中圈出来的这段话,段落标题为An ACID Alternative,英语好的小伙伴可以翻译一下,啥意思?ACID的替代品,想要理解论文这段话,我们先来说说ACID理论(在论文中也有前置说明)。

3.1、ACID理论

在之前《全解MySQL专栏》的《事务篇》中,曾对传统关系型数据库的ACID理论做了详细讲述,ACID对应着四个特性。

  • Atomicity原子性:将组成事务的多个操作,视为一个不可分割的整体,要么全部成功,要么全部失败,不能只生效一部分;
  • Consistency一致性:事务执行前后,数据库只能从一个一致状态转为另一个一致状态,即事务执行对整体数据产生的变化是一致的;
  • Isolation隔离性:多事务并发执行时,各事务之间不能被其他事务干扰,就类如每个事务都在独立的沙箱中执行;
  • Durability持久性:一旦事务提交,无论发生什么状况(如故障、宕机等),该事务对数据的变更都会永久保存。

这里重点把一致性拉出来聊聊,ACID中的一致性定义为:一个事务执行前后,数据库只能从一个一致状态转变为另一个一致状态,这句话有点绕对吧?其实在之前的事务篇中举例解释过,现在再以“转账”这个典型的事务场景案例来说:

需求:小竹向熊猫账户里转1000W元。
数据库现状:小竹账户余额为1001W元,熊猫账户余额为888W元。

面对上述这个需求,对应的转账事务为:小竹账户先减1000W,熊猫账户再加1000W。所谓的一致性,就是这个事务执行前后,数据库里的整体数据变化一致,对其进行拆解:

  • 初始态:小竹账户余额为1001W元,熊猫账户余额为888W元。
  • 结果态:小竹账户余额为1W元,熊猫账户余额为1888W元。

如果该事务执行失败,数据库应该回到初始态,这对数据库来说状态没有改变;而当该事务执行成功时,数据库应该来到结果态,此时小竹+熊猫的账户余额,合计还是1889W,对数据库整体状态来说,也并未改变,这就是ACID里所谓的一致性:事务执行前后只会从一个一致状态转为另一个一致状态

当然,上面这段拆解对有些小伙伴来说,或许还是有点绕,那再举反例说明,即聊聊“不一致”的场景:

  • ①小竹账户减1000W,余额1W,但熊猫账户没有加,还是888W,合计889W
  • ②熊猫账户加1000W,余额1888W,但小竹账户没有减,还是1001W,合计2889W

上述则是两种没有保证一致性的场景,事务执行前后,整体数据的变化并不一致,造成数据库陷入了一种不正确的状态。

其他事务场景也是同理,下单时,[库存数减一,订单数加一]、[库存数不变,订单数不变],这属于一致状态,出现这两种情景之外的现象,则说明数据库未保证一致性。

PS:其实有点类似于能量守恒定律,能量在转化或转移的过程中,总量保持不变……

上面的转账事务例子,如果刚执行完减钱动作,接着数据库发生故障/宕机,恢复后,又会导致数据不一致。所以完全满足ACID里的一致性,也得考虑数据库故障/宕机对一致性的影响(这里不做展开,感兴趣可参考《MySQL事务恢复机制》)。

3.2、重新理解BASE理论

OK,简单回顾了一下ACID理论,现在再来看BASE论文里的那段:ACID的替代品

分布式事务 cap base理论,系统架构,分布式

来简单翻译下这段话:

如果ACID为分布式数据库提供了一致性选择,那如何在分布式数据库里保证可用性呢?一个答案就是BASE理论。

BASE理论与ACID完全相反,ACID是悲观思想,在每次操作结束时强制要求保持一致性(即事务结束必须落入终态)。而BASE是乐观思想,可以接受数据库一致性处于不断变化的状态。虽然听起来……

翻译了前两句话,从这两句话里不难看出,BASE理论的最终一致性,并不是用来对标CAP的一致性,而是与ACID里的一致性对等,允许事务执行后出现“中间态”

来个分布式事务的经典例子:

分布式事务 cap base理论,系统架构,分布式

商品库里有个“黄金竹子”,库存数为8888,现在有个对应的下单请求(暂时抛开实际下单场景中的复杂流程),对应的事务则为[库存减一、创建一条订单],如果遵循ACID里的一致性,此时只能有两种状态:

  • 初始态:黄金竹子库存为8888,没有对应的订单。
  • 结果态:黄金竹子库存为8887,有一条对应的订单。

在分布式场景中,因为商品服务和订单服务是分开部署的,所以要通过网络调用“创建订单”的接口,可网速再怎么快,就算是内网环境,扣完库存到创建订单之间也会有时间差,这就导致分布式系统中会出现短暂的“不一致”:

  • 中间态:黄金竹子库存为8887,没有对应的订单记录。

如果在这个中间态期间,出现一个读取“黄金竹子库存数”的请求,就会看到8887这个库存数。因此,正是因为这个中间态的存在,就违背了ACID原则,ACID定义的一致性不接受这种现象。

再回头看,BASE理论中,软状态的定义允许存在中间态,最终一致性的定义接受延迟性,所以这也是为什么BASE理论的论文中说:BASE是分布式场景中ACID理论代替品的本质原因!

好了,再把BASE理论中的最终一致性,代入到上面的案例中,如果下单事务执行结束,流向会有两个:

  • 新增订单成功,分布式事务可以提交,中间态流转到结果态。
  • 新增订单失败,分布式事务触发回滚,中间态撤回到初始态。

综上所述,不管中间态是流转到结果态,还是撤回到初始态,最终系统内整体数据的变化是一致的,这也就是所谓的“最终一致性”。

PS:分布式事务如何保证最终一致性,后续会有单独的分布式事务篇章进行讲述,本文不再展开。

3.3、为什么很多人聊CAP会扯到BASE?

上阶段证实了一开始提出的观点,BASE理论的初衷,是为了成为分布式系统中ACID理论的替代者,跟CAP理论没什么太大关系。可为什么一抓一大把的资料,都在潜意识的表达“BASE理论是对CAP理论的补充”这种观点呢?

因为CAP理论只能在A、C中,二者选其一,选了A不能选C,要了C不能要A。可是有些人又想要A,又想要C,于是就把BASE理论抬出来做解释,声称:BASE理论可以让我们不必在A、C中做抉择,而是可以实现部分的AC

奔着三人成虎的原则,你这样喊,他也这样喊,我还这样喊……,越来越多的人就都认为BASECAP的补充版……。其实不然,就连CAP、BASE两个理论中的一致性定义都不同,CAP的一致性,关注的是数据一致性;BASE的一致性,关注的是状态一致性,真正的对应关系如下:

CAP一致性 ≠ BASE一致性、BASE一致性 = ACID一致性。

同时,两个理论除开一致性的定义不同外,甚至连“可用性”的定义也不一样。CAP中的可用性,是指主从这类集群,某个节点出现故障时,不会影响系统整体的运行,如:

分布式事务 cap base理论,系统架构,分布式

上图这个MySQL多主集群,两个节点互为对方的从机,业务应用任意连接某个节点,都可以读写完整数据。当某个节点出现故障时,业务应用都可以连接另一个节点,正常读写数据,这是CAP关注的可用性(响应速度也是CAP可用性的一种表现)。

反观BASE理论,其中定义的“基本可用”,更多针对于分片式领域,来看论文中这段话:

分布式事务 cap base理论,系统架构,分布式

翻译过来的意思就是:如果用户数据跨五个数据库服务器存储,根据BASE理论,一台数据库出现故障,仅仅只会影响到20%的用户。用户数据跨五个数据库存储,意味着什么?看过之前《MySQL分库分表篇》的小伙伴应该清楚,这代表着用户数据做了水平拆分,所有用户数据会根据特定的规则,分发到五个不同的节点中分开存储!

正因如此,才会给出“一个节点故障只会影响20%用户”这个结论,毕竟存储其他80%数据的四个节点此时正常。所以,BASE理论中的基本可用,并不是指主从这类“全量式复制”的集群,而是针对“分片式”的集群。

PS:BASE论文中还提到按功能拆分的思想,其中称为“功能组”,就类似如今的按业务分库,感兴趣可去阅读原文。

好了,既然CAP、BASE的定义都不同,为什么这么多人会把这两个扯上关系呢?究其根本原因是:BASE理论中定义的三个概念,几乎能覆盖大多数分布式场景

BASE理论的最终一致性,虽然是指状态一致性,可是也能套入CAP的数据一致性,比如主从集群数据复制,如果选同步-复制,太影响性能;如果选异步-复制,可以最快程度上响应请求,同时数据也会同步给从机,虽然有时间差,但只要集群内节点正常运转,所有节点的数据,最终都会保持一致。

异步-复制模式中,如果数据刚落入主节点,而后主节点就宕机,尽管选上来的新主会丢失一部分数据,但也不是不能用对吧?为此,BASE定义的基本可用,也能套上CAP的可用性~

BASE理论比CAP晚诞生十年,两者所处的时代背景不同,BASE定义的维度比CAP要高,所以在一定程度上,BASE能向下兼容CAP,这也就让许多人觉得BASECAP理论的拓展。

四、总结

通篇看完,大家会发现CAP理论并没有那么强大,它的作用更多局限于分布式存储领域,同时也并非整个分布式存储领域都会用到CAP思想,如今主流的分片式存储架构,就摒弃了传统的CAP模型。

BASE理论,则广泛运用于各类分布式系统,其中定义的三个概念,覆盖了分布式系统的大多数场景,比如微服务中的服务降级、熔断、限流机制,就是“基本可用”的一种体现。

最后,在之前的文章中,我一直强调大家不要听风就是雨,学习技术时,务必保持审慎怀疑的态度!比如本文讨论的BASE理论,90%资料都在告诉你,它是CAP的拓展理论,可事实却并非如此。为此,大家学习时要多思考、做验证,这样才能真正的把技术学透彻。文章来源地址https://www.toymoban.com/news/detail-849385.html

到了这里,关于深入浅出 -- 系统架构之分布式CAP理论和BASE理论的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 深入浅出 -- 系统架构之微服务架构选型参考图

    技术选型架构图 是一个用于展示项目中所采用的各种技术和组件之间关系的图表。 它通常包括以下几个部分: 1. 项目名称和描述:简要介绍项目的背景和目标。 2. 技术栈:列出项目中使用的主要技术和工具,如编程语言、框架、数据库等。 3. 组件关系:用箭头表示各个组

    2024年04月09日
    浏览(48)
  • 深入浅出 -- 系统架构之微服务架构的新挑战

    尽管微服务架构有着高度独立的软件模块、单一的业务职责、可灵活调整的技术栈等优势,但也不能忽略它所带来的弊端。本篇文章,我们从网络、性能、运维、组织架构和集成测试五个方面来聊一下设计微服务架构需要考虑哪些问题,对设计有哪些挑战呢? 前面我们聊过了

    2024年04月09日
    浏览(53)
  • 深入浅出 -- 系统架构之负载均衡Nginx反向代理

    一、Nginx反向代理-负载均衡  首先通过 SpringBoot+Freemarker 快速搭建一个 WEB 项目:springboot-web-nginx,然后在该项目中,创建一个 IndexNginxController.java 文件,逻辑如下: 在该 Controller 类中,存在一个成员变量: port ,它的值即是从 application.properties 配置文件中获取 server.port 值。

    2024年04月12日
    浏览(54)
  • 深入浅出 -- 系统架构之Keepalived搭建双机热备

    Keepalived+重启脚本+双机热备搭建 ①首先创建一个对应的目录并下载 keepalived 安装包(提取码:s6aq)到 Linux 中并解压: ②进入解压后的 keepalived 目录并构建安装环境,然后编译并安装: ③进入安装目录的 /soft/keepalived/etc/keepalived/ 并编辑配置文件: ④编辑主机的 keepalived.conf

    2024年04月11日
    浏览(46)
  • 深入浅出 -- 系统架构之负载均衡Nginx的性能优化

       到这里文章的篇幅较长了,最后再来聊一下关于 Nginx 的性能优化,主要就简单说说收益最高的几个优化项,在这块就不再展开叙述了,毕竟影响性能都有多方面原因导致的,比如网络、服务器硬件、操作系统、后端服务、程序自身、数据库服务等,对于性能调优比较感兴

    2024年04月14日
    浏览(49)
  • 深入浅出 -- 系统架构之负载均衡Nginx实现高可用

       线上如果采用单个节点的方式部署 Nginx ,难免会出现天灾人祸,比如系统异常、程序宕机、服务器断电、机房爆炸、地球毁灭....哈哈哈,夸张了。但实际生产环境中确实存在隐患问题,由于 Nginx 作为整个系统的网关层接入外部流量,所以一旦 Nginx 宕机,最终就会导致整

    2024年04月15日
    浏览(48)
  • 深入浅出 -- 系统架构之负载均衡Nginx跨域配置

       跨域问题在之前的单体架构开发中,其实是比较少见的问题,除非是需要接入第三方 SDK 时,才需要处理此问题。但随着现在前后端分离、分布式架构的流行,跨域问题也成为了每个Java开发必须要懂得解决的一个问题。 跨域问题产生的原因    产生跨域问题的主要原因就

    2024年04月10日
    浏览(53)
  • 深入浅出 -- 系统架构之负载均衡Nginx大文件传输配置

       在某些业务场景中需要传输一些大文件,但大文件传输时往往都会会出现一些 Bug ,比如文件超出限制、文件传输过程中请求超时等,那么此时就可以在 Nginx 稍微做一些配置,先来了解一些关于大文件传输时可能会用的配置项: 配置项 释义 client_max_body_size 设置请求体允

    2024年04月12日
    浏览(72)
  • 深入浅出 -- 系统架构之微服务标准组件及职责

    我们来认识一下微服务架构在Java体系中依托哪些组件实现的。 相对于单体架构的简单粗暴,微服务的核心是将应用打散,形成多个独立提供的微服务,虽然从管理与逻辑上更符合业务需要。但微服务架构也带来了很多急需解决的核心问题: 1、如何发现新节点以及检查各节点

    2024年04月12日
    浏览(50)
  • 深入浅出 -- 系统架构之微服务中Nacos的部署

    前面我们提到过,在微服务架构中,Nacos注册中心属于核心组件,通常我们会采用高性能独立服务器进行部署,下面我们一起来看看Nacos部署过程: 因为Nacos是支持windows和Linux系统的,且服务器操作系统一般都是Linux的,为了大家看完文章,可以按照步骤一步步把Nacos部署好,

    2024年04月10日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包