CAP理论,是分布式系统中最基础、最重要的理论之一。

它由计算机科学家埃里克·布鲁尔,在2000年的ACM PODC会议上提出,所以也叫"布鲁尔定理"。CAP理论告诉我们,一个分布式系统,不可能同时满足以下三个特性:

  • C(Consistency):一致性,所有节点,在同一时间,看到的数据是一致的。
  • A(Availability):可用性,每个请求,都能在有限的时间内,得到响应。
  • P(Partition Tolerance):分区容错性,当网络分区发生时,系统仍然能继续工作。

CAP理论说,这三个特性,最多只能同时满足两个,不可能三个都满足。所以,分布式系统,要么是CP系统,要么是AP系统,没有CAP系统。

我第一次接触CAP理论,是在三年前。那时候,我刚做分布式系统,觉得CAP理论很简单,不就是三选二嘛,记住就行了。但是,用了三年,做了很多分布式系统,踩了很多坑,我才慢慢明白,CAP理论,远不是三选二那么简单。它里面,有很多微妙的地方,有很多容易误解的地方,有很多需要在实践中才能体会的道理。

今天,我想分享一下,我用了三年CAP理论,才明白的一些道理。希望能给正在学习分布式系统,或者正在做分布式系统的朋友,一些参考和启发。

一、道理一:P不是可选的,是必须的

刚学CAP理论的时候,我以为,C、A、P三个,是平等的,可以任选两个。你可以选CA,可以选CP,可以选AP,看你的需求。

但是,做了三年分布式系统,我才明白:P不是可选的,是必须的。

为什么?因为,分布式系统,必然是分布式的,必然有多个节点,节点之间,必然通过网络通信。而网络,是不可靠的,必然会出现网络分区。网络分区,就是节点之间,网络不通了,分成了几个区域,区域之间,无法通信。

网络分区,是分布式系统中,必然会发生的事情。不管你的网络多么可靠,不管你用了多少冗余,网络分区,总有可能发生。网线可能被挖断,交换机可能故障,路由器可能宕机,机房可能断电,DDoS攻击可能导致网络拥塞。这些,都会导致网络分区。

所以,在分布式系统中,P(分区容错性),是必须的,是前提,不是可选的。你不能说,我选CA,不要P。因为,只要是分布式系统,就必然有网络分区的可能,你必须能容忍网络分区,否则,你的系统,就不是一个真正的分布式系统。

既然P是必须的,那么,CAP理论,实际上就变成了:在网络分区发生的时候,你只能在C和A之间选一个。要么选C(一致性),牺牲A(可用性);要么选A(可用性),牺牲C(一致性)。没有第三个选择。

这就是CAP理论的真正含义:在分布式系统中,当网络分区发生时,一致性和可用性,不可兼得,你必须二选一。

很多人,刚学CAP理论的时候,都以为CA系统是存在的。比如,MySQL主从复制,是不是CA系统?不是的。因为,MySQL主从复制,也是分布式系统,也有网络分区的可能。当网络分区发生时,主库和从库之间,无法通信,这时候,你要么选C(等网络恢复,数据一致了再提供服务,牺牲可用性),要么选A(继续提供服务,但是数据可能不一致,牺牲一致性)。没有CA系统。

所以,记住:P不是可选的,是必须的。CAP理论,实际上是在网络分区时,C和A的二选一。

二、道理二:C和A,不是非黑即白的,是有程度的

刚学CAP理论的时候,我以为,C和A,是二元的,非黑即白的。要么满足C,要么不满足C;要么满足A,要么不满足A。系统,要么是CP系统,要么是AP系统,清清楚楚。

但是,做了三年分布式系统,我才明白:C和A,不是非黑即白的,是有程度的,是一个连续谱。

先说C(一致性)。一致性,有很多种,强一致性、弱一致性、最终一致性、因果一致性、读己之写一致性,等等。强一致性,是最严格的,所有节点,在同一时间,看到的数据完全一致。最终一致性,是最宽松的,不保证同一时间数据一致,但是保证,经过一段时间后,数据最终会一致。中间,还有各种不同程度的一致性。

所以,C,不是一个二元的概念,不是要么有,要么没有,而是有程度的。你可以选择强一致性,也可以选择最终一致性,也可以选择中间的某种一致性。不同的一致性程度,对系统的性能、可用性、复杂度,都有不同的影响。

再说A(可用性)。可用性,也不是二元的。可用性,通常用百分比来表示,比如99%、99.9%、99.99%、99.999%。99%的可用性,意味着每年有3.65天的 downtime;99.999%的可用性,意味着每年只有5分钟的 downtime。可用性,是一个程度的概念,不是要么有,要么没有。

而且,可用性,还和延迟有关。CAP理论中的A,要求每个请求,都能在有限的时间内,得到响应。但是,"有限的时间",是多长?100毫秒?1秒?10秒?如果你的系统,每个请求都能响应,但是需要10秒,这算满足A吗?严格来说,算,因为在有限时间内响应了。但是,从用户体验来说,10秒的响应,和不可用,差不多。所以,可用性,也和延迟有关,是一个程度的概念。

既然C和A,都是有程度的,那么,系统,就不是简单的CP或AP,而是在C和A的连续谱上,找到一个平衡点。你可以选择强一致性,高可用性(但是,在网络分区时,还是要二选一);也可以选择最终一致性,更高的可用性;还可以选择,在正常情况下,强一致性,在网络分区时,降级为最终一致性。

很多分布式系统,都是这样做的。比如,Google的Spanner,号称是"CA"系统,但是,它实际上是在C和A之间,找到了一个很好的平衡点。它通过TrueTime API,实现了外部一致性,同时,通过Paxos算法,实现了高可用性。当然,在网络分区时,它还是要在C和A之间做选择,但是,它通过技术手段,把网络分区的影响,降到了最低。

所以,记住:C和A,不是非黑即白的,是有程度的。不要简单地把系统分为CP或AP,要根据业务需求,在C和A的连续谱上,找到最合适的平衡点。

三、道理三:CAP,是在网络分区时的选择,不是常态

刚学CAP理论的时候,我以为,CAP理论,是分布式系统的常态。也就是说,分布式系统,永远只能满足两个,永远要在C和A之间做选择。所以,CP系统,永远是一致性的,永远牺牲可用性;AP系统,永远是可用的,永远牺牲一致性。

但是,做了三年分布式系统,我才明白:CAP,是在网络分区时的选择,不是常态。

CAP理论,说的是,当网络分区发生时,你只能在C和A之间选一个。但是,网络分区,不是常态,是异常情况。在正常情况下,网络没有分区,节点之间通信正常,这时候,你可以同时满足C和A。

比如,一个CP系统,在正常情况下,是既一致,又可用的。只有当网络分区发生时,它才会牺牲可用性,保证一致性。一个AP系统,在正常情况下,也是既一致,又可用的。只有当网络分区发生时,它才会牺牲一致性,保证可用性。

所以,CAP理论,不是说,分布式系统,永远只能满足两个,而是说,在网络分区这个异常情况下,你只能在C和A之间选一个。在正常情况下,你可以同时满足C和A。

这一点,很重要。因为,很多人,因为CAP理论,就觉得,分布式系统,要么不一致,要么不可用,做分布式系统,就是在C和A之间做痛苦的选择。其实不是的。在正常情况下,分布式系统,可以同时满足C和A,既一致,又可用。只有在网络分区这个异常情况下,才需要做选择。

而且,网络分区,发生的概率,其实不高。只要你的网络,设计得合理,有足够的冗余,网络分区,是很少发生的。大部分时间,系统都是正常的,都能同时满足C和A。

所以,记住:CAP,是在网络分区时的选择,不是常态。不要因为CAP理论,就觉得分布式系统,永远只能满足两个。在正常情况下,分布式系统,可以同时满足C和A。

四、道理四:选择CP还是AP,要看业务场景

刚学CAP理论的时候,我以为,CP比AP好,强一致性比最终一致性好。所以,做系统的时候,总是倾向于选CP,选强一致性,觉得这样更高级,更可靠。

但是,做了三年分布式系统,我才明白:选择CP还是AP,要看业务场景,没有绝对的好坏。

不同的业务场景,对一致性和可用性的要求,是不一样的。有些业务,对一致性要求很高,对可用性要求相对低一些,这时候,应该选CP。有些业务,对可用性要求很高,对一致性要求相对低一些,这时候,应该选AP。

适合选CP的场景:

  • 金融交易:比如,银行转账、支付、证券交易。这些业务,对一致性要求极高,钱不能错,账不能乱。如果数据不一致,可能会导致严重的经济损失,甚至法律问题。所以,这些业务,通常选CP,牺牲可用性,保证一致性。网络分区时,宁可暂停服务,也不能让数据出错。
  • 库存管理:比如,电商的库存、火车票的座位、酒店的房间。这些业务,对一致性要求也很高,不能超卖,不能重复销售。如果数据不一致,可能会导致超卖,影响用户体验,甚至导致赔偿。所以,这些业务,通常也选CP。
  • 账户信息:比如,用户的余额、积分、优惠券。这些业务,对一致性要求也很高,不能出错。如果数据不一致,可能会导致用户的财产损失。

适合选AP的场景:

  • 社交动态:比如,朋友圈、微博、Twitter。这些业务,对可用性要求极高,用户随时都能发动态,看动态。对一致性要求相对低一些,用户晚几秒看到别人的动态,没关系。所以,这些业务,通常选AP,牺牲一致性,保证可用性。
  • 商品浏览:比如,电商的商品列表、商品详情。这些业务,对可用性要求很高,用户随时都能浏览商品。对一致性要求相对低一些,商品的价格、库存,晚几秒更新,没关系(但是,下单的时候,还是要保证一致性)。所以,这些业务,通常选AP。
  • 评论、点赞:比如,文章的评论、点赞数。这些业务,对可用性要求很高,用户随时都能评论、点赞。对一致性要求相对低一些,评论晚几秒显示,点赞数晚几秒更新,没关系。所以,这些业务,通常选AP。
  • 日志、监控数据:比如,系统日志、监控指标。这些业务,对可用性要求很高,随时都能写入和查询。对一致性要求相对低一些,数据晚几秒同步,没关系。所以,这些业务,通常选AP。

所以,选择CP还是AP,不是看哪个更高级,而是看业务场景。适合业务场景的,才是最好的。如果业务对一致性要求高,就选CP;如果业务对可用性要求高,就选AP。不要盲目追求强一致性,也不要盲目追求高可用性,要根据业务需求,做合适的选择。

而且,很多系统,不是简单的CP或AP,而是混合的。不同的模块,不同的功能,可以有不同的选择。比如,电商系统,商品浏览模块,可以选AP,保证高可用;下单和支付模块,可以选CP,保证一致性。这样,既保证了核心业务的一致性,又保证了非核心业务的可用性。这才是合理的架构。

所以,记住:选择CP还是AP,要看业务场景,没有绝对的好坏。适合业务场景的,才是最好的。而且,系统可以是混合的,不同模块,不同选择。

五、道理五:BASE理论,是CAP中AP的延伸

刚学CAP理论的时候,我以为,CAP理论,就是全部了,选CP或AP,就完事了。但是,做了三年分布式系统,我才明白,CAP理论,只是基础,还有一个重要的理论,叫BASE理论,是CAP中AP的延伸。

BASE理论,是对CAP中AP系统的进一步阐述,它的核心思想是:即使无法做到强一致性,但是可以通过适当的方式,达到最终一致性。BASE,是三个短语的缩写:

  • BA(Basically Available):基本可用。分布式系统,在出现故障时,允许损失部分可用性,保证核心功能可用。比如,响应时间变长,或者功能降级,但是系统仍然可用。
  • S(Soft State):软状态。允许系统存在中间状态,这个中间状态,不会影响系统的整体可用性。也就是说,允许数据在不同节点之间,暂时不一致。
  • E(Eventually Consistent):最终一致性。系统中的所有数据副本,经过一段时间的同步后,最终能够达到一致的状态。不需要实时保证数据一致,但是最终要一致。

BASE理论,和传统的ACID(原子性、一致性、隔离性、持久性),是相对的。ACID,强调的是强一致性,是数据库事务的特性;BASE,强调的是最终一致性,是分布式系统的特性。

BASE理论,是AP系统的指导思想。AP系统,牺牲了强一致性,保证了可用性,但是,它不是不要一致性,而是通过最终一致性,来保证数据的一致性。数据,暂时可以不一致,但是最终要一致。

比如,Amazon的Dynamo,就是一个典型的BASE系统。它通过NWR机制(N个副本,写W个,读R个),来调节一致性和可用性的平衡。当W+R>N时,是强一致性;当W+R<=N时,是最终一致性。Dynamo,默认是最终一致性,保证高可用性,但是,数据最终会一致。

再比如,很多电商系统,商品的库存,在浏览的时候,是最终一致性的,不同的用户,可能看到不同的库存数,但是,最终会一致。但是,在下单的时候,会通过分布式锁,或者事务,保证强一致性,不会超卖。

所以,BASE理论,是AP系统的核心思想。做AP系统,不是不要一致性,而是要通过BASE理论,实现最终一致性。既要保证高可用性,又要保证数据最终一致。

所以,记住:BASE理论,是CAP中AP的延伸。做AP系统,要理解BASE理论,实现最终一致性,而不是完全放弃一致性。

六、道理六:CAP理论,不是分布式系统的全部

刚学CAP理论的时候,我以为,CAP理论,就是分布式系统的全部,掌握了CAP理论,就掌握了分布式系统。但是,做了三年分布式系统,我才明白:CAP理论,只是分布式系统的基础,不是全部。

分布式系统,是一个非常庞大、非常复杂的领域。CAP理论,只是其中的一个基础理论,它告诉我们,在网络分区时,C和A不可兼得。但是,分布式系统,还有很多其他的理论、技术、问题,需要我们去学习和掌握。

比如:

  • 一致性算法:Paxos、Raft、ZAB,这些一致性算法,是实现分布式一致性的核心。CAP理论,只是告诉我们,一致性和可用性不可兼得,但是,怎么实现一致性,怎么在保证一致性的同时,尽可能提高可用性,需要一致性算法。
  • 分布式事务:2PC、3PC、TCC、Saga、本地消息表、事务消息,这些分布式事务方案,是解决分布式系统中事务一致性的核心。CAP理论,只是告诉我们,强一致性和高可用性不可兼得,但是,在实际业务中,怎么实现事务的一致性,需要分布式事务方案。
  • 服务发现和负载均衡:分布式系统中,服务的注册、发现、负载均衡,是基础功能。怎么实现服务发现,怎么实现负载均衡,怎么处理服务的故障,这些,都是分布式系统的重要问题。
  • 分布式锁:分布式系统中,怎么实现分布式锁,怎么保证锁的正确性和性能,怎么处理锁的死锁和超时,这些,都是分布式系统的常见问题。
  • 限流、熔断、降级:分布式系统中,怎么处理高并发,怎么保护系统,怎么防止雪崩,这些,都是分布式系统的重要问题。
  • 数据分片和复制:分布式系统中,怎么对数据进行分片,怎么对数据进行复制,怎么保证数据的一致性和可用性,这些,都是分布式系统的核心问题。
  • 可观测性:分布式系统中,怎么监控系统的状态,怎么追踪请求的链路,怎么分析系统的日志,这些,都是分布式系统的重要问题。

这些,都是分布式系统的重要内容,都不是CAP理论能涵盖的。CAP理论,只是分布式系统的入门理论,是基础。要真正掌握分布式系统,还需要学习很多其他的理论和技术。

而且,CAP理论,本身也有一些局限性。比如,CAP理论,只考虑了网络分区,没有考虑其他的故障,比如节点宕机、磁盘故障、数据损坏等。再比如,CAP理论,只考虑了一致性和可用性,没有考虑延迟、吞吐量、可扩展性等其他重要的系统指标。所以,CAP理论,不是分布式系统的全部,只是其中的一部分。

所以,记住:CAP理论,只是分布式系统的基础,不是全部。不要以为掌握了CAP理论,就掌握了分布式系统。要真正掌握分布式系统,还需要学习很多其他的理论和技术。

七、写在最后

CAP理论,是分布式系统中,最基础、最重要的理论之一。但是,它也是最容易被误解的理论之一。

我用了三年,做了很多分布式系统,踩了很多坑,才慢慢明白,CAP理论,远不是三选二那么简单。P不是可选的,是必须的;C和A,不是非黑即白的,是有程度的;CAP,是在网络分区时的选择,不是常态;选择CP还是AP,要看业务场景;BASE理论,是AP的延伸;CAP理论,不是分布式系统的全部。

这些道理,有的是从书本上学来的,有的是从实践中踩坑踩出来的。只有真正做过分布式系统,真正遇到过网络分区,真正在C和A之间做过痛苦的选择,才能真正理解CAP理论的深刻含义。

CAP理论,虽然简单,但是,它的思想,是深刻的。它告诉我们,在分布式系统中,没有完美的方案,只有权衡和选择。我们要根据业务需求,在一致性和可用性之间,找到最合适的平衡点。没有最好的系统,只有最适合业务的系统。

最后,用一句话来结束这篇文章:"CAP理论,不是三选二的简单选择题,而是分布式系统设计的哲学。它告诉我们,没有完美,只有权衡;没有最好,只有最合适。理解了CAP,就理解了分布式系统的一半。"

希望这篇文章,能给你带来启发。如果你有不同的观点,或者有什么补充,欢迎在评论区留言,我们一起交流。