CAP 理论常被解释为一种“三选二”定律,这是否是一种误解?
问题:
此处的 CAP 理论指的是计算机科学中分布式系统领域的一条已经证明的定律。
我对这个定律的证明没有疑虑。但现实生活中,大部分人解释这一定律时,常常简单地表述为:“一致性、可用性、分区容忍性三者你只能同时达到其中两个,不可能同时达到”
这是否符合 CAP 定律的本意?这样的描述是否存在误解?
谢谢每一位回答者。
回答:
分区容忍是分布式这个问题的根源,也就是说分区出错了,我们到底选择CP,还是AP?
选择CP,系统继续运转,出错分区因为通讯故障,数据无法保证一致性。反之选择AP,系统不能运转,直到出错分区修复或替换,保证数据一致性。
但如果选择CA,那就是必须有一个前提了,分区不存在容忍的情况,也是P始终不会出现。这个问题能成立吗?留到最后讲Google F1和Spanner我们看看。
我仅通过分布式数据库架构的几个CAP实践,主要看看CAP应用的地方,这个很关键,因为CAP也并不是那么绝对的有你没我,举例说明:
01
MySQL主从架构
MySQL主从我们可以理解成一种分布式的数据库架构,它的应用需求就是复制形成副本。
一个特别典型的例子就是MySQL的主从复制架构:异步,半同步,全同步。
1). 异步:尽管主库保证了数据的强一致性,但是数据一旦写给binlog,主库就无视了从库的一致性,继续忙自己的事情,那么这个过程就是异步的,从库从binlog中拿到结果再重放保证与主库的一致性。这个过程就是典型的最终一致性。
上述的分布式过程就是彻底地放弃了一致性C,保全了可靠性A和容错性P。更具体的描述就是:从库哪怕挂了,主库依然及时响应客户(A),系统也还正常运转(P)
2). 半同步:MySQL 主库写入binlog后,至少集群中任意一个MySQL从库反馈主库,它同步成功了,那么主库就继续忙自己的事了,我们可以把这个过程称为弱一致性。
上述的分布式过程就不是完全放弃一致性,还留了点,至少有一个从库要给回应,就是任意一个从库还正常的话,就不影响给用户的及时响应(A),但是真的有出错的从库,一致性依然是失败的,但我们保证了数据至少拥有了一组正常的副本。
3).全同步:自然不用想了,MySQL主库写入binlog,集群其他节点都要重放后,报告同步成功了,主库才会忙其他事情,这就是分布式环境的强一致性了!
这个过程就是放弃可靠性了(A),只要有任意一个节点在复制过程中出现故障,那么系统对客户的响应就要停下来。
因此弱一致性是在强一致性和最终一致性中寻找一个平衡,至少有一个备份点是必须与主保持一致的,那么数据的可靠性是不是就提升了,同时性能上也不至于太差了。
02
MongoDB副本集
我们再看看MongoDB的副本集架构,它在副本集模式下,可以灵活地设置一致性规则,其中majority选项的意思是主库写入oplog后,大多数成员需要确认才行。
这又是一种平衡CAP定理的模式,什么叫大多数成员需要确认才行,也就是集群中至少超过一半的节点都没有故障的话,主节点就认为复制过程没有问题。从一致性C角度看,大多数节点都没有问题了,一致性应该是趋向于强一致性,从可靠性角度(A)看即便出现低于一半的节点堵塞了,是不会影响到系统对客户的响应的。我认为这个模式和半同步一样其实都是一种平衡策略,让大多数情况在可靠性和一致性上寻求一种平衡。
03
谷歌的F1和Spanner
有没有违反CAP定理模式的呢?有!就是谷歌的F1和Spanner,既保证了一致性,还保证了可靠性,那么从计算机科学中分布式系统领域已经证明的CAP定理上看,是不是这个案例就和科学现象硬刚上了!
主要应用就是分布式环境下,数据库的事务处理,我对此了解不深,只能简单描述F1和spanner的在数据表结构变更的情况下,如何保证所有节点的一致性与可靠性共存:
一般来看,数据表结构若是需要变更,分布式环境下正在运行的不同节点,获取数据结构变更的时间肯定不一样,那么为了保证一致性,就让所有的服务节点都下线停止工作,统一完成更新了再上线,那么系统的可靠性就放弃了;反之,若在线直接对每个节点进行更新,虽然客户系统的响应没有问题,但是数据结构变更导致的各个节点不同步,一定会出现工作处理的数据错误,这就是放弃了一致性。
咱们看看F1和spanner如何保证一致性与可靠性共存的策略:
1). 它们的解决思路是分布式所有服务器通过对时间的精准约定实现一致性和可靠性的共存。
2). 所有节点必须有精准的时间概念,那么就需要一个精准授时机制,Spanner用GPS和原子钟实现的时间API,将数据中心各个节点的时间同步精确到10ms以内。
3). 数据结构的变更会通知所有节点,在一个约定的时间段内变更前与变更后的数据结构是共存的,那么在这个时间段内所有节点有可能已经更新,也有可能未更新,关键是节点进行工作处理的过程不受影响。
4). 为了让各个节点在工作处理的过程中不受变更的影响,那么每次变更的内容都是小幅递进的,从而兼容了变更前后的工作处理。
5). 过了约定的时间点,那么系统一定会认为所有的节点都是变更后的数据结构了,若没有变更成功的节点,会直接退出。
好吧,不得不说基于spanner论文对分布式关系数据库的设计实在是太精妙了!
好吧,不得不说基于Spanner论文对分布式关系数据库的设计实在是太精妙了!
摘抄一段CAP理论提出者Eric Brewer,同时也是谷歌基础设施副总裁撰文:
“这是否意味着Spanner是CAP定义的CA系统?简短的答案是技术上“不是”,但效果上“是”,用户可以并确实认为是CA系统。
声明“实际上是CA”系统,那么,这个系统必须处于这种相对概率状态:
1)系统必须在生产环境中具有非常高的可用性(以便用户可以忽略异常),
2)系统由于分区引起的宕机故障次数应该处于一个比较低的份额。
Spanner满足两者。”
Spanner让分区P不会出现的几率提升至9.9999%,这是用户可以接受的,因此,从实际情况看,限定条件P出现情况极低,可以视为不存在了。那么就保证了CA。
从技术上讲,如果非要吹毛求疵认为0.0001%的分区存在的话,那Spanner就是CP。但是实际效果上看,作为一个全球分布式系统,应该很难看到比Spanner更能保证CA共存的高可用,低故障系统了。
(END)
如果觉得写得不错,文章对你有用,请在文末「在看,分享和赞」三连击
——点击“阅读原文”即可获取更多精彩内容——
本文分享自微信公众号 - 读字节(read-byte)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
bee-spring-boot V1.9.5 版正式发布,轻松整合 Bee 和 Spring-boot
bee-spring-bootV1.9.5(青年版) Bee 1.9.5 整合 Spring-boot 1.5.16.RELEASE 并且提供bee-spring-boot-starter. maven依赖: <dependency> <groupId>org.teasoft</groupId> <artifactId>bee-spring-boot</artifactId> <version>1.9.5</version> </dependency> 直接使用相应starter: <parent> <groupId>org.teasoft</groupId> <artifactId>bee-spring-boot-starter</artifactId> <version>1.9.5</version> </parent> 相应demo: https://gitee.co...
- 下一篇
一文抽丝剥茧带你掌握复杂Gremlin查询的调试方法
摘要:Gremlin是图数据库查询使用最普遍的基础查询语言。Gremlin的图灵完备性,使其能够编写非常复杂的查询语句。对于复杂的问题,我们该如何编写一个复杂的查询?以及我们该如何理解已有的复杂查询?本文带你逐步抽丝剥茧,完成复杂查询的调试。 本文分享自华为云社区《复杂Gremlin查询的调试方法》,原文作者:Uncle_Tom。 1. Gremlin简介 Gremlin是Apache TinkerPop 框架下的图遍历语言。Gremlin是一种函数式数据流语言,可以使得用户使用简洁的方式表述复杂的属性图(property graph)的遍历或查询。每个Gremlin遍历由一系列步骤(可以存在嵌套)组成,每一步都在数据流(data stream)上执行一个原子操作。 Gremlin是一种用于描述属性图中行走的语言。图形遍历分两个步骤进行。 1.1. 遍历源(TraversalSource) 开始节点选择(Start node selection)。所有遍历都从数据库中选择一组节点开始,这些节点充当图中行走的起点。Gremlin中的遍历是从TraversalSource开始的。 Grap...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8安装Docker,最新的服务器搭配容器使用
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8编译安装MySQL8.0.19