分布式系统概念
单机就不说了,分辨一下「集群」和「分布式」的区别:
- 集群是相同应用的多备份部署,同一份代码,功能相同,相当于多台单机,有效负载均衡,不过耦合度太高。
- 分布式则是将业务拆成了多个不同的子业务,每个子业务有单独的服务部署,这些子业务构成一个完整的系统。
熟悉了分布式的概念,这里需要强调一下「分布式」和「微服务」的关系:
- 微服务是一种软件设计理念,它是面向服务的,将大的系统或者是服务,拆分成一组小的且相互独立的服务。这些小的服务都是都是独立运行的,并且每个小服务有自己的数据库、业务逻辑,服务之间通过网络进行通信和协作。这组小服务一起协作对外提供服务,共同完成一个系统的任务。
- 微服务其实是一种特定的分布式系统架构风格,分布式是一种系统架构的范畴,而微服务是分布式系统的一种具体实现方式,微服务将应用程序拆分成小的、自治的服务单元,通过网络进行通信和协作来完成系统任务。分布式有很多种实现方式,微服务并不是它唯一的实现方式。
分布式理论基础
由于分布式系统中的程序是部署在多个节点上的,各个节点通过网络通信。一旦有网络通信,就会有网络的可靠性问题,延迟问题,以及各个节点的故障问题等等。可能出现有的节点能正常工作,而有的节点挂掉,导致有的请求达到正常节点就能正常处理,而打到故障节点又会失败。又或者因为网络故障,导致有的写操作在部分节点成功,而在另一些节点失败,总之可能存在种种状态不一致的情况,这些问题的存在影响着系统在高性能,高可用等方面的设计。而随着分布式的发展,人们总结出了一套分布式设计理论,这套理论对于后来分布式系统设计有着指导意义,这就是大名鼎鼎的 CAP 理论。
CAP 原理
更多:阮一峰|CAP 定理
1. CAP 理论由来
Lynch 教授提出了一个影响深远的概念,如在一个不稳定(要么消息错乱,要么消息丢失)的网络环境里(异构模型),想始终保持数据一致是不可能的,这个概念为后来 CAP 理论的发展奠定了重要基础。
在 CAP 理论出来之前,并没有一个明确的方向性的指导。所以在设计实现分布式系统时会显得很混乱。可能在分布式系统中,不同的子模块有着不同的设计标准,对同一个系统而言,这显然不是很合理
比如在一个由两个模块构成的分布式系统中,这两个模块 A 和 B 之间能够互相通信
A 模块的设计原则是:A 发送请求给其他模块,如果节点间出现了故障,会选择不断的重试,一直等到节点通信恢复。可以理解为提供高质量服务。
B 模块的设计原则是:B 发送请求给其他模块,如果节点间出现了故障,会选择直接断开,并记下当前状态,等待后续处理,可以理解为提供高可用服务。
显然,系统中如果出现了通信故障,A 往 B 发请求,会出现不断重试,而 B 往 A 发请求,则会出现直接断开的情况,整个系统会很混乱。
所以,IT界的研究者们长期以来一直在探索指导原则来指导分布式系统的设计,在 2000 年 Eric Brewer 教授在 PODC 会议上首次提出了 CAP 理论。然而,当时这一理论还没有被正式证明,所以只能称为 CAP 猜想。
这个猜想一经提出,就在业界引起了极大的关注,因为它为分布式系统设计提供了一个简单而有力的框架。到了 2002 年,Seth Gilbert 和 Nancy Lynch 通过理论证明了 CAP 猜想的正确性,从而使 CAP 理论正式确立,并成为分布式系统设计中的重要理论基础之一。
2. CAP 理论
在一个分布式系统中,一致性(Consistency)、可用性(Availability)和分区容错性(Partition Tolerance)这三个目标无法同时满足,最多只能同时满足其中的两个。
2.1 数据一致性(C)
「数据一致性」是指在分布式系统中的所有节点,在同一时间点上拥有相同的数据副本。比如某个节点数据有更新,那么其他的节点数据要跟着更新,要求所有的读请求都必须读到这个新数据。
- 写操作(增、删、改):数据变更
- 读操作
当数据服务有多个节点的时候,当数据服务接收到写请求时,怎样判定数据服务上所有的节点都一起发生了变更呢?
- 当然有的分布式系统由不同的策略配置,比如 MySQL 的主从集群,当配置为全同步时,即每次写数据只有当主库把数据都同步到从库后,才会返回成功,这样返回写成功后,称之为数据一致性改变。
- 如果不是这种配置策略,比如半同步,只有部分从库同步完了数据,也会返回成功,那么从从库读数据的话,可能就会读取不到新值,就不能称之为数据一致性改变。
假设「一主两从」的 MySQL 集群系统,在网络通信正常情况下,如果经过一次写请求后,两个从库节点都发生了数据变化。然后,读请求把这些变化后的数据都读取到了,我们就把这次数据修改称为数据发生了一致性改变。
假设系统内部发生了通信问题,主库和从库 2 之间的通信发生了故障,而主库和从库 1 之间的通信正常,那么写入操作成功之后,从库 1 可以读取到 V1 版本数据,而从库 2 无法读取到 V1 版本数据,地区到的还是旧数据。此时,系统中的节点就没有发生一致性改变。
2.2 可用性(A)
「可用性」是指系统要处于 100% 的可用状态,对于每一个请求,正常节点要在合理的时间给出正确的响应,即系统能够正常提供服务。
- 必须在合理时间内给出响应,时间根据业务要求来定。
- 只要正常的节点都能做出响应(无论数据是否最新):
- 如果系统内的某个节点或者是某些节点宕机了,但是其他的正常节点可以在合理的时间内做出响应。
- 节点正常,但是节点上的数据有问题,比如不是最新数据,如果有请求达到这个节点上了,依然不能拒绝请求,要正常返回这个旧数据。
2.3 分区容错性(P)
「分区容错性」是指分布式系统能够在网络分区的情况下继续运行对外提供服务,即系统能够在节点之间进行通信的网络出现故障或延迟的情况下,保证系统的正常运行。
网络分区
网络分区只在分布式集群中,在分布式系统中,多个节点之间的网络本来是连通的,但是由于某些故障导致节点之间网络不通了,形成不同的子集,子集中节点之间网络互通,而子集与子集之间网络不通,整个网络就形成了几块区域,就是网络分区。
上图中,G1 和 G2 是两台跨区的服务器。G1 向 G2 发送一条消息,G2 可能无法收到。系统设计的时候,必须考虑到这种情况。
一般来说,分区容错无法避免,因此可以认为 CAP 的 P 总是成立。CAP 定理告诉我们,剩下的 C 和 A 无法同时做到。
3. CAP 为什么不能同时满足
这个问题看似是论证一致性、可用性、分区容忍性为什么只能选择其中的两个同时满足,其实并非如此。因为在分布式系统中分区容错性(Partition-tolerance ) 是不得不选择的。假设不考虑分区容错性,那就相当于把数据只存放在一个节点上,因为数据依旧集中在一个地方,一旦这个节点出现故障,整个系统毫无疑问会随之瘫痪,这在实际的生产环境中通常是不可接受的,而且数据集中在一个地方,这本身也与分布式相矛盾。
✅ 在分布式系统中,分区容错性( P )是一定要满足的,剩下的一致性( C )和可用性( A )只能满足其一。因此,分布式架构不可能选择 CA 架构,只能选择 CP 架构 或者 AP 架构。
- 由于存在分区容错性,所以存在 server2 写入 X=2 失败,而 server1 写入 X=2 成功,那么此时 client2 和 client3 就会读取到不一样的值,client2 读取到 X=2,而 client3 读取到 X=1,此时系统可用,但是违背了一致性,保证了 A,但是违背了 C,属于 AP 架构。
- 假设此时要保持 X 值的一致性,server1 和 server2 的 Write 操作必须同时成功,系统必须等待 server2 也写入成功,在失败的这段时间里,系统是不可用状态,这样的话就保证了一致性 C,但是也降低了系统的可用性,违背了 A,此时属于 CP 架构。
由此可见,在分布式系统中,无法同时满足 CAP 定律中的 “一致性”、“可用性” 和 “分区容错性” 三者。
4. CAP 如何选择
任何方案选型都要根据业务场景出发,看业务场景适合哪种,就选哪种,一般而言:
- CP 使用场景:比较典型的 CP 系统是分布式数据库,数据的一致性是最基本的要求。在极端情况时,优先保证数据的强一致性,代价就是放弃系统的可用性。例如,类似 Redis、HBase 这种分布式存储系统,以及 ZooKeeper 这种分布式协调系统。另一个常见场景就是金融领域,为了资金安全一般需要确保强一致性。
- AP 使用场景:AP 则是适应于目前大多数对于用户体验要求高的互联网应用场景,比如社交媒体,内容分发业务,像微博、Instagram。用户量大,主机众多,分布式部署,而且集群的规模越来越大,节点故障、网络故障时有发生,要保证系统的可用性,保障 AP 放弃 CP 是常见的一种做法。
5. CAP 的不足
CAP 最大的不足其实也就是一致性(Consistency)、可用性(Availability)的强取舍问题。
在实际应用中,一致性和可用性并不只是简单的二选一问题,而是取决于各自的优先级。当我们强调一致性时,并不意味着系统的可用性会完全丧失。比如,在 Zookeeper 中,只有在主节点出现问题时,系统才可能会出现短暂的不可用状态,但在其他时间,系统通过各种方式来保证其可用性。同样,强调可用性时,通常也会采用技术手段来确保数据最终能够保持一致性。CAP 定理并没有详细说明这些细节。
✅ 其实简单来说,就是在设计分布式系统时,对于一致性和可用性希望有一些折中的手段,而不是选择了其中一个特性,就要完全舍弃另一个特性。
BASE 原理
正因为 CAP 理论存在一些局限性,eBay 的架构师 Dan Pritchett 基于他在大规模分布式系统中的实践经验,总结出了 BASE 理论。BASE 理论是对 CAP 理论的进一步扩展,其核心思想是,即便无法实现强一致性(Strong Consistency),应用程序也可以通过适当的方法达到最终一致性(Eventual Consistency)。
BASE 理论是一个更具工程实践意义的理论,它弥补了 CAP 理论过于抽象的问题,同时也为 AP 系统提供了整体的工程实践思想。目前 BASE 理论已经成为分布式系统中的核心理论之一。
1. 数据一致性
BASE 理论对数据一致性做了一些更细致的分类,从而对 CAP 理论作了进一步的扩展。数据一致性大致可以分为以下几类:
1.1 强一致性
数据更新操作完成之后,数据立即生效,后续的所有访问当中都能得到最新的结果。
1.2 弱一致性
数据更新操作完成之后,不要求立即可以读到最新写入的值,能容忍在更新发生之后,部分情况下无法访问到新数据的情况。
1.3 最终一致性
数据更新操作完成之后,能容忍更新后一段时间内无法访问到最新数据,不需要实时保证系统数据的强一致性,但是经过一段时间的同步之后,最终可以达到一个一致的状态。所以,最终一致性可以看作是弱一致性的一个特例。
而在 CAP 理论中的 C 指的是强一致性,所以要分析什么样的系统适合 AP,什么样的系统适合 CP,其实就是在强一致性和可用性之间做权衡,根据业务情况,看那些业务能够容忍最终一致性,而很在乎用户体验,这样的业务就适合 AP,而对于强一致性要求高的业务则适合用 CP。
2. BASE
- BA 基本可用(Basically Available):系统在遇到不可预知的故障时,允许损失部分可用性,就是说即使系统不能完全正常工作,但是仍然有部分功能可用。换句话说,但至少能够提供部分服务。例如,响应时间比平时长或者某些功能暂时不可用。
- 响应性能变弱:比如正常情况下请求响应为 0.3s,但是出现了某个故障之后,虽然还能正常响应,但是响应时长变为了 2s
- 系统功能有损:比如商城双十一活动时,评论模块出现故障,但不会影响交易、商品等核心模块的流程使用
- S 软状态(Soft state):指允许系统中的数据存在中间状态,这种状态可能是不一致的,但是这种中间状态的存在不会影响系统的整体可用性,因为数据在不同节点之间的同步可能存在延迟。
- E 最终一致性(Eventual Consistency):系统不要求数据实时地达到一致性,而是允许数据在一段时间后最终达到一致状态。这意味着在经过一定的时间之后,所有副本的数据会最终到达一致的状态。
既然在分布式系统中分区容错性我们无法回避,而根据 CAP 理论,我们要么选择 AP 模型,要么选择 CP 模型。但是在很多的场景中,尤其是对可用性要求高的场景往往既需要可用性,又想保证一致性,这里就出现了矛盾。所以这里可以在选择可用性的同时,弱化强一致性,但是并不是永远放弃一致性,在分区故障恢复后,根据各自的业务特点,经过一段时间系统应该达到最终一致性。而系统中一部分不一致时,系统仍需要保持系统整体“主要可用”,也就是基本可用。其实 Base 理论可以理解为:分区容错性 + 基本可用性 + 最终一致性;其实就是对 CAP 理论的一种延伸。