本文原文链接
45岁老架构 尼恩说在前面
在45岁老架构师 尼恩的读者交流群(100+)中,最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团、蚂蚁、得物的面试资格,遇到很多很重要的相关面试题:
- 聊聊CAP 定理?
- CAP不能同时被满足,为什么?
- AP/CP不能兼顾?为什么?
- 哪些中间件是AP? 哪些中间件 是CP? 说说为什么?
最近有小伙伴面试字节,都问到了这个面试题。 小伙伴没有系统的去梳理和总结,所以支支吾吾的说了几句,面试官不满意,面试挂了。
所以,尼恩给大家做一下系统化、体系化的梳理,使得大家内力猛增,可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”,然后实现”offer直提”。
当然,这道面试题,以及参考答案,也会收入咱们的 《尼恩Java面试宝典PDF》V175版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。
《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请到文末公号【技术自由圈】获取
1.背景介绍
数据一致性是分布式系统中的一个重要问题,它涉及到多个节点之间的数据同步和一致性。
数据一致性问题在分布式系统中具有重要的意义。
而 CAP定理是一个关于分布式系统的一致性模型。 CAP定理 是 分布式系统的 底层定理, 也是 面试的核心重点。
接下来, 尼恩带大家来 穿透 CAP定理,哪些中间件是AP,哪些中间件 是CP,让面试官 口水直流。
2.CAP定理
2.1 CAP 猜想/CAP证明/CAP定理
CAP 猜想
CAP 定理(CAP theorem)又被称作 布鲁尔定理 ,是加州大学伯克利分校的计算机科学家埃里克·布鲁尔(Eric Brewer)在 2000 年的 ACM PODC 上提出的一个猜想。
CAP 证明
2002 年,麻省理工学院的赛斯·吉尔伯特(Seth Gilbert)和南希·林奇(Nancy Lynch)发表了布鲁尔猜想的证明,使之成为分布式计算领域公认的一个定理。
CAP 定理
CAP 该定理指出一个 分布式系统 最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。
CAP定理的三个要素可以用来描述分布式系统的一致性和可用性。
三个要素包括:
- 一致性(Consistency) C
- 可用性(Availability) A
- 分区容错性(Partition Tolerance) P
2.2 CAP定理 的三要素以及 三要素之间的 关系 :
CAP定理 的内容:一个分布式系统无法同时满足这三个条件,只能满足两个,意味着我们要抛弃其中的一项。
cap三个要素:
- C:一致性是指所有节点 的数据是否一致,或者说,一份数据的多个分布式副本 是否一致
- A: 可用性是 指系统在任何时刻都能提供服务
- P :分区容错性是指系统在网络分区(/ 局部断网)的情况下, 仍然 能提供服务。
2.2.1 一致性(Consistency)
一致性是指所有节点 的数据是否一致,或者说,一份数据的多个分布式副本 是否一致。
注意, CAP里边的可用性 C, 强调是 任何时刻 一致, 指的是强一致性。
一般来说,在分布式系统中 的一致性可以分为两种类型:强一致性和弱一致性。
强一致性要求在任何时刻,所有节点都能看到相同的数据。
而弱一致性允许在某些情况下,部分节点可能看到不同的副本。
尼恩啰啰嗦嗦的说一下:CAP里边的 C 指的是 强一致性。
2.2.2 可用性(Availability)
可用性是指系统在任何时刻都能提供服务。
注意, CAP里边的可用性 A, 强调是 任何时刻 可用, 指的是 高可用,或者说 99.99%可用。
一般来说, 在分布式系统中,可用性是一个重要的指标,它可以用来衡量系统的稳定性和可靠性。
可用性通常被定义为系统在一段时间内无法提供服务的概率,通常使用99.9%(即99.9%的时间内系统可用)来衡量。
尼恩啰啰嗦嗦的说一下:CAP里边的 A 指的是 高可用性, 比如 企业级软件的 4个9。
一般来说, 可用性 有个衡量 的标准——X个9,这个X是代表数字3~5, 具体如下表:
可用度A | 9的个数 | 年内不可用时间(分钟) | 适用产品 |
---|---|---|---|
0.999 | 三个9 | 526分钟 | 个人电脑 |
0.9999 | 四个9 | 52.6分钟 | 企业级软件 |
0.99999 | 五个9 | 5.26分钟 | 互联网产品 |
0.999999 | 六个9 | 0.5分钟 (31s) | 电信级基础设施 |
X个9表示在系统1年时间的使用过程中,系统可以正常使用时间与总时间(1年)之比,我们通过下面的计算来感受下X个9在不同级别的可靠性(Reliability)差异。
1个9:(1-90%)*365=36.5天
2个9:(1-99%)*365=3.65天
3个9:(1-99.9%)36524=8.76小时,表示该系统在连续运行1年时间里最多可能的业务中断时间是8.76小时。
- 4个9:(1-99.99%)36524=0.876小时=52.6分钟,表示该系统在连续运行1年时间里最多可能的业务中断时间是52.6分钟。
- 5个9:(1-99.999%)36524*60=5.26分钟,表示该系统在连续运行1年时间里最多可能的业务中断时间是5.26分钟。
- 6个9:(1-99.9999%)365246060=31秒
可以看到1个9和、2个9分别表示一年时间内业务可能中断的时间是36.5天、3.65天,这种级别的可靠性(Reliability)或许还不配使用“可靠性(Reliability)”这个词;
而6个9则表示一年内业务中断时间最多是31秒,那么这个级别的可靠性(Reliability)并非实现不了,而是要做到从“5个9” 到“6个9”的可靠性(Reliability)提升的话,后者需要付出比前者几倍的成本。
2.2.3 分区容错性(Partition Tolerance)
分区容错性是指系统在网络分区(/ 局部断网)的情况下, 仍然 能提供服务。
在分布式系统中,网络分区是一个常见的问题,它可能导致系统的故障和数据丢失。因此,分区容错性是一个重要的一致性要素,它可以帮助我们确保系统在网络分区的情况下仍然能够正常工作。
尼恩啰啰嗦嗦的说一下:CAP里边的 P 指的一定是 分布式系统, 单节点系统,不能算CAP里边 的P。
2.2.4 CAP 三要素 之间的 冲突的关系
CAP定理 的内容:一个分布式系统无法同时满足这三个条件,只能满足两个,意味着我们要抛弃其中的一项。
CAP定理的关键:是 三个要素之间的关系。
CAP定理告诉我们,在分布式系统中,一致性 C、可用性 A 和分区容错性 P 是相互冲突的。
1、CA,放弃P:强调 单节点, 单副本,或者只有一个正本,没有副本。 简单说,CA 将所有数据都放在一个分布式节点上,这同时放弃了系统的可扩展性, 不属于 分布式系统范围了。
2、CP,放弃A:强调副本之间的 强一致性, 意味着 低性能。 一旦系统遇到故障时,受影响的服务器需要等待一段时间,在恢复期间无法对外提供正常的服务。
3、AP,放弃C:强调副本之间的 高性能, 意味着 弱一致性。这里的放弃一致性是指放弃数据强一致性,而保留数据的最终一致性。系统无法实时保持数据的一致,但承诺在一个限定的时间窗口内,数据最终能够达到一致的状态。
即使我们尝试去优化这三个要素,但是最多只能实现两个要素。 CA 、CP、AP 只能 三选一:
3 CAP定理的实践意义: 强一致性 和 高并发的 选择
CAP定理的实践意义在于它帮助我们在设计分布式系统时,明确一致性、可用性和分区容错性之间的关系,从而能够更好地权衡这三个要素,以确保系统的正常运行。
3.1 CP( 强一致性) VS (高可用性) AP
CAP理论告诉我们,一致性、可用性和分区容错性是相互冲突的。
作为 分布式系统, 分区容错性 P 是必不可少的, 所以只能在 AP 、CP之间,二选一:
因此,CAP定理给我们提供了一个有限的选择空间,我们需要根据具体的需求来选择适当的一致性模型。
- 要么 CP 强一致性
- 要么 AP 高可用性
二者 不可兼得, 天然冲突。
总之, CAP 这是数学证明了的。 CAP 是铁律。
所以,我们需要在设计分布式系统时,权衡一致性和可用性之间的关系,CP 强一致性 和 AP 高可用性 2选一,以确保系统的正常运行。
4. 常用中间件的 CAP 定理
4.1 redis Cluster 是 ap 型
首先 分析一下 redis Cluster 的 分区容错性(P)
Redis Cluster 采用去中心化的架构,节点之间通过 Gossip 协议来进行信息交换。Gossip 协议就像在集群中 “传播小道消息”,每个节点 周期性地向其他节点发送状态信息, 也会接收其他节点传来的信息。这种方式使得集群能够快速感知到网络分区的情况。
当网络分区发生时,例如部分节点之间无法通信,Redis Cluster 依然能够正常工作。
它会根据集群配置和节点状态,让每个分区内的节点尽可能地独立运行。
例如,在数据分片(Redis Cluster 将数据分成 16384 个槽位,分布在不同节点上)的情况下,每个分区内的节点可以继续处理自己负责槽位的读写请求,保证系统不会因为网络分区而完全瘫痪,体现了良好的分区容错能力。
再 来分析一下 redis Cluster 的 可用性(A)
在正常情况下,客户端可以向任意主节点发送读写请求。即使在节点故障转移过程中,大部分读写请求依然能够得到处理。
Redis Cluster 具备高效的故障转移机制。 每个主节点都有对应的从节点,当主节点出现故障时,从节点会通过选举机制快速晋升为主节点。
例如,假设一个主节点因为硬件故障或者网络问题无法正常工作,从节点能够在很短的时间(通常在毫秒级)内检测到这种情况,并开始竞选成为新的主节点。
一旦竞选成功,新的主节点就可以接收客户端的读写请求,保证服务的可用性。
最后 分析一下 redis Cluster 的 一致性(C)
Redis Cluster 没有选择强一致性,而是采用了最终一致性。
这是因为在保证高可用性和分区容错性的同时,强一致性会带来性能上的巨大损耗。
例如,在主从复制过程中,如果要求每次写操作都必须等待从节点同步完成才能返回成功,会大大增加写操作的延迟。
Redis Cluster 通过异步复制的方式来维护数据的一致性。
主节点接收写请求后,会异步地将数据复制给从节点。
在正常情况下,这种异步复制能够快速地将数据传播到从节点。
当出现故障转移时,新晋升的主节点可能会丢失一部分还没来得及复制的数据,但系统会在后续通过数据恢复机制(如从其他节点获取丢失的数据副本)来使数据最终达到一致。
这种对一致性的权衡使得 Redis Cluster 更符合 AP 系统的特点。
总之 : redis Cluster 是 ap 型。
4.2 zookeeper 是 cp 型
首先 分析一下 zookeeper 的 分区容错性(P)
当网络分区发生时,例如部分节点之间无法通信,Zookeeper 集群会尝试重新建立连接。
如果分区情况,会通过 过半机制,形成多数派+ 少数派,然后放弃少数派。
例如,一个集群有 5 个节点,因为分区变成了两个子集群,一个子集群有 2 个节点(多数派),另一个有 3 个节点(多数派),那么:
(多数派)3 个节点的子集群可以继续工作 ,
少数派2 个节点 会暂停服务,以避免数据不一致。
这样做虽然会牺牲部分节点的可用性,但保证了整个集群的一致性和分区容错性。
再 来分析一下 zookeeper 的 可用性(A)
Zookeeper 为了确保一致性,在一定程度上牺牲了可用性。
在网络分区或者节点故障导致无法形成多数派的情况下,少数派节点会被隔离,不能提供服务。
例如,如果一个集群有 3 个节点,当一个节点故障,剩下两个节点还可以继续工作;
但如果出现网络分区,将 3 个节点分成两个单独的部分(如 1 个节点一组和 2 个节点一组),那么只有 2 个节点的那一组可以工作,1 个节点的那一组会停止服务,直到网络分区恢复或者节点重新加入多数派。
这种设计使得 Zookeeper 更侧重于一致性和分区容错性,符合 CP 系统的特点。
最后 分析一下 zookeeper 的 一致性(C)
Zookeeper 使用 ZAB(Zookeeper Atomic Broadcast)协议来保证一致性。
在 ZAB 协议中,当一个事务(如节点数据的更新)被提议时,它会通过一个类似于两阶段提交的过程在集群中传播。
首先是广播阶段,主节点(leader)会将事务提议发送给所有的从节点(follower)。
然后是提交阶段,当多数从节点都成功接收并持久化这个提议后,主节点才会提交这个事务,并且通知所有从节点也提交,这样就确保了所有节点要么都执行这个事务,要么都不执行,从而保证了数据的一致性。
两阶段的 事务, 意味着网络上 有很多次 IO 通讯,这是是低性能的。
总之 : zookeeper 是 cp 型。
4.3 MongoDB 属于 C P
MongoDB 是一个流行的 NoSQL 数据库管理系统,它将数据存储为 BSON(binary JSON)文档。
MongoDB 是一个单一的主系统,每个副本集只能有一个主节点来接收所有的写操作。
同一副本集中的所有其他节点都是辅助节点,它们复制主节点的操作日志并将其应用于自己的数据集。
默认情况下,客户机也从主节点读取数据,但他们也可以指定一个允许他们从辅助节点读取数据的读取首选项。
当主节点不可用时,具有最新操作日志的次节点将被选为新的主节点。
一旦所有其他次要节点都赶上新的主节点,集群将再次可用。由于在此期间客户端无法发出任何写请求,因此数据在整个网络中保持一致。
相对于 CAP 定理,MongoDB是一个 CP 数据存储,它通过保持一致性来解决网络分区问题,同时降低可用性。
4.4 Cassandra 属于 AP
Apache Cassandra 是由 Apache 软件基金会维护的 开源 NoSQL 数据库。
Cassandra 是一个列式数据库,允许您在分布式网络上存储数据。
Cassandra 与 MongoDB 不同 ,Cassandra 拥有一个无主的架构。
因为 Cassandra 没有主节点,所以所有节点必须连续可用。
然而,Cassandra 允许客户机在任何时候向任何节点写入数据并尽快协调不一致,从而提供了最终的一致性。
按照 CAP 定理去分析, Cassandra 是一个 AP 数据库 ,它提供高并发,但不能强一致性。
4.5 Eureka 属于 AP
网易一面:Eureka怎么AP?Nacos既CP又AP,怎么实现的?
首先看看 Eureka 可用性(A)。
Eureka 采用去中心化的架构,各个 Eureka Server 之间相互对等,没有主从之分。
这意味着即使有部分 Eureka Server 出现故障,其他的 Eureka Server 依然可以继续工作。
例如,在一个包含多个 Eureka Server 的数据中心中,如果一台 Eureka Server 因为硬件故障或者网络问题无法工作,剩余的 Eureka Server 能够接手其工作,继续为服务提供者和消费者提供注册和发现服务,不会因为某个节点的故障而导致整个系统无法运行。
另外,在分布式环境中,网络可能会出现波动或者短暂的故障, Eureka 有一个重要的自我保护机制。
当 Eureka Server 在短时间内丢失大量的心跳连接(例如,由于网络抖动,很多客户端与服务端之间的心跳连接中断),它 不会立即清除这些看起来已经 “死掉” 的服务实例。而是进入自我保护状态,在这个状态下,Eureka Server 仍然会对外提供服务,包括已有的注册信息。
这就保证了在网络不稳定的情况下,Eureka Client 服务消费者仍然能够获取到可能还在正常运行的服务实例信息,尽可能地维持服务的可用性。
再 看看 Eureka 分区容错性(P)
在面对网络分区的情况时,Eureka 更侧重于保证可用性。
例如,当网络分区导致部分 Eureka Server 和服务实例之间无法通信时,Eureka 会允许每个分区继续工作。
每个分区内的服务实例可以在自己所属的分区内进行注册和发现服务。
这样就避免了因为网络分区而导致整个系统无法使用,体现了良好的分区容错性。
不过,这种情况下可能会出现数据不一致的情况,例如不同分区对于服务实例的状态(如是否可用)可能有不同的认知,但这是为了优先保证系统的可用性和分区容错性所做出的权衡。
最后,看看 Eureka 的一致性(C)的权衡
Eureka 没有采用强一致性模型。
在服务注册和发现的过程中,Eureka 更关注服务的可用性。 Eureka 允许在一定时间内不同 Eureka Server 之间的数据存在差异。
例如,当一个服务实例刚刚注册到一个 Eureka Server 时,其他 Eureka Server 不会立即获取到这个信息,
例如,当一个服务实例状态发生改变(如从可用变为不可用),这个信息在所有 Eureka Server 中同步可能会有延迟。
牺牲数据的一致性,就是因为CAP定理来的,是为了提高系统的整体性能和可用性,使得 Eureka 更符合 AP 系统的特点。
4.6 Nacos 属于 AP 又 AP
网易一面:Eureka怎么AP?Nacos既CP又AP,怎么实现的?
Nacos 属于 AP 又 AP ? 看上去 ,这个 违背了CAP 定理。
还有天理吗? 其实,还有。
还有王法吗? 其实,还有。
先看看 nacos 的 永久节点、 临时节点。
client 永久节点
当client
节点注册在 Nacos 时, 设置ephemeral = false
时,注册的节点为永久节点。
与临时节点不同,永久节点的信息会一直保存在 Nacos 的服务注册表中,除非通过明确的删除操作,否则不会因为服务实例的健康状态变化而自动移除。
这意味着即使服务实例出现故障(如网络中断、进程崩溃等),其在 Nacos 中的注册信息依然存在。
client 临时节点
在 Nacos 中,当client
节点注册时设置ephemeral = true
,表示该节点是一个临时节点。
临时节点主要用于服务发现场景下的临时服务实例注册。
临时节点 与永久节点(ephemeral = false
)相对,临时节点的生命周期与服务实例的健康状态直接相关。
如果服务实例出现故障(如网络中断、进程崩溃等),Nacos 会自动将该临时节点从服务列表中删除。
默认的微服务实例, 是 client 临时节点
Nacos 支持 CP+AP 模式, 其实和 CAP 不冲突
Nacos 支持 CP+AP 模式,这意味着 Nacos 可以根据配置识别为 CP 模式或 AP 模式,默认情况下为 AP 模式。
- 临时节点 AP: 如果注册Nacos的client节点注册时ephemeral=true,那么Nacos集群对这个client节点的 状态维护使用 AP模式,采用distro协议实现;
- 永久节点 CP:而注册Nacos的client节点注册时ephemeral=false,那么Nacos集群对这个节点的状态维护使用 CP模式,采用raft协议实现。
根据client注册时的属性,AP,CP只能二选一 ,只是对不同的client节点效果不同.
总之, 同一个 节点, 要么CP、要么AP,只能二选一 。
因此,Nacos 能够很好地满足不同场景的业务需求。
高端面试:必须来点 高大上的答案:
尼恩 想说的是:
要拿到 高薪offer, 或者 要进大厂,答案的太 平庸/太普通的话 是不够的,而且是远远不够。
要拿到 高薪offer, 或者 要进大厂,必须来点 非常见的、 高大上的答案, 整点技术狠活儿。
如果能讲 到尼恩答案 的 水平 , 面试官一定口水直流, 大厂 offer 就到手啦。
尼恩架构团队,持续为大家 梳理了一系列的 塔尖 面试题,帮助大家 进大厂,拿高薪:
- Java基础
美团面试:String 为什么 不可变 ?(90%答错了,尼恩来一个绝世答案)
- 索引
阿里面试:为什么要索引?什么是MySQL索引?底层结构是什么?
滴滴面试:单表可以存200亿数据吗?单表真的只能存2000W,为什么?
- 索引下推 ?
- 索引失效
美团面试:mysql 索引失效?怎么解决?(重点知识,建议收藏,读10遍+)
- MVCC
- binlog、redolog、undo log
美团面试:binlog、redolog、undo log底层原理是啥?分别实现ACID哪个特性?(尼恩图解,史上最全)
- mysql 事务
京东面试:RR隔离mysql如何实现?什么情况RR不能解决幻读?
- 分布式事务
分布式事务圣经:从入门到精通,架构师尼恩最新、最全详解 (50+图文4万字全面总结 )
说在最后:有问题找45岁老架构取经
只要按照上面的 尼恩团队梳理的 方案去作答, 你的答案不是 100分,而是 120分。 面试官一定是 心满意足, 五体投地。
按照尼恩的梳理,进行 深度回答,可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”,然后实现”offer直提”。
在面试之前,建议大家系统化的刷一波 5000页《尼恩Java面试宝典PDF》,里边有大量的大厂真题、面试难题、架构难题。
很多小伙伴刷完后, 吊打面试官, 大厂横着走。
在刷题过程中,如果有啥问题,大家可以来 找 40岁老架构师尼恩交流。
另外,如果没有面试机会, 可以找尼恩来改简历、做帮扶。前段时间,空窗2年 成为 架构师, 32岁小伙逆天改命, 同学都惊呆了。
狠狠卷,实现 “offer自由” 很容易的, 前段时间一个武汉的跟着尼恩卷了2年的小伙伴, 在极度严寒/痛苦被裁的环境下, offer拿到手软, 实现真正的 “offer自由” 。
尼恩技术圣经系列PDF
- 《NIO圣经:一次穿透NIO、Selector、Epoll底层原理》
- 《Docker圣经:大白话说Docker底层原理,6W字实现Docker自由》
- 《K8S学习圣经:大白话说K8S底层原理,14W字实现K8S自由》
- 《SpringCloud Alibaba 学习圣经,10万字实现SpringCloud 自由》
- 《大数据HBase学习圣经:一本书实现HBase学习自由》
- 《大数据Flink学习圣经:一本书实现大数据Flink自由》
- 《响应式圣经:10W字,实现Spring响应式编程自由》
- 《Go学习圣经:Go语言实现高并发CRUD业务开发》
……完整版尼恩技术圣经PDF集群,请找尼恩领取
《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF,请到下面公号【技术自由圈】取↓↓↓