本文旨在帮助读者理解CAP定理,能够从CAP定理出发去分析、理解一些架构设计。
我们不生产概念,我们只是概念的搬运工。CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。看图说话:

乍一看,有人不禁会发问:“凭啥不能三者兼顾,老子凭借多年代码经验和架构设计经验,还搞不定你的一个三者兼顾的设计?......嗯.......CAP定理到底啥意思来着?”。也许从某个角度出发,你想的还挺有道理,我们再来理解下CAP:
1、C(Consistency)一致性,也叫可线性化,这里指强一致性。
例如:你和同事偷偷在上班时间看某年世界杯新闻,你同事刷新页面后看到了中国足球已经夺冠,并把这个可靠的消息告诉了你,你可能有点儿不敢相信,也拿出同样的app刷新闻,结果你的请求被发送到一个数据库的备份(数据可能还没同步过去),显示比赛还在继续....结果是后来刷新的人反而拿到了旧的结果,显然不满足一致性(线性化)。所以一致性至少保证两人同时刷新时拿到同样结果。
2、A(Availability)可用性,每一个请求如果被一个工作中的(数据库)节点收到,那一定要返回(非错误)的结果。这里指高可用,即每次请求都要有返回(一般这种情况就会考虑多个节点且每个节点都支持请求并都能返回结果)。
3、P(Partition tolerance)分区容错,意思是大部分信息交互在异步网络中完成,信息是可能延迟送达或者被丢失的。互联网还有我们所有的数据中心都有这个属性。所以我们在这件事上我们一般没有选择,这就是为什么我们一般只考虑AP架构或者CP架构的原因。
那么,为什么在网络分区的情况下不得不放弃可用性和一致性中的一个?
我们来看一个场景,你的数据库有两个备份在两个不同的数据中心。希望是当数据被写到一个数据中心的时候,他也一定要被写到另一个数据中心。假设其中一个用户只连接到某一个数据中心,不巧的是连接两个数据中心的网络故障了。面对这种情况,预案是啥,怎么搞?

你可能有两个选择:
选择1:你的应用还是被允许写到数据库,所以两边的数据库还是完全可用的。但是一旦两个数据库之间的网络中断了,任何一个数据中心的写操作就不会在另一个数据中心出现。这就违反了一致性。
选择2:为保障可用性,你就必须保证你的读写操作都在同一个数据中心,你可能叫它 Leader。另一个数据中心,因为网络故障不能被更新,就必须停止接收读写操作,直到网络恢复,两边数据库又同步了之后。所以虽然非 Leader 的数据库在正常运行着,但是他却不能处理请求,这就违反了 CAP 的可用性定义。
实际应用中的可用性和 CAP 可用性并不相同,也并不能保证你的设计一定就满足了CP或者AP。你应用的可用性多数是通过 SLA 来衡量的(比如 99.9% 的正确的请求一定要在一秒钟之内返回成功)。
思考:区块链理论上也是分布式存储数据库,同样面临CAP定理问题,P是必须要保证的,那么如何在C和A中取舍?
区块链是依靠概率强一致性(Probabilistic strong consistency)实现一致性共识的,称为共识。先来看一下区块链的记录方式:区块链大概每10分钟会分配出一个新的区块,这是靠很多机器不断地进行哈希计算出来的,如果两组机器算力相同,它们就会创建两个不同版本的新区块,然后就各自将这10分钟内自己知道的所有交易加入到这个区块中,并且广播到自己周围,周围的节点在这区块以后再增加新的区块,形成了两条新的区块链,也就是分叉,各自有各自的树型结构,但是区块链内部机制有一个原则,选择最长的那条区块链,丢弃其他的。这个机制其实非常类似现实自由选举制,选举人在各个州获得支持,最后获得越多人支持的获胜。
当区块链客户端在交易一加入区块链就立即接受,好处是不依赖其他节点,能够立即可用,是CAP的AP,但是风险是可能丧失强一致性,其他节点可能会丢弃这笔交易,因为其所在的区块链分叉在竞争性的选举中失败了。
为了获得CP,客户端应该等待区块链大多数节点接受了这笔交易再真正接受它,说明这笔交易所在分叉已经选举胜利,获得大部分共识,获得了强一致性,但是风险是可能不可用unavailable ,丧失CAP的A,因为网络分区通信等问题可能阻止这种共识。
注:本文部分内容摘抄于网络,如有侵权请联系作者删除!




