Linux:CAP定理——分布式计算
一、起源与发展
CAP(Consistency、Availability、Partition Tolerance)(一致性、可用性、分区容忍性)也叫Brewer定理,由Eric Brewer于2000年提出。
2002年,Seth Gilbert和Nancy Lynch用严谨的数学推理证明了CAP猜想。从此CAP正式从猜想变成了分布式计算领域工人的著名定理。该定理描述了一个分布式系统中,涉及共享数据问题时,CAP三个特性最多只能满足其中两个。
二、概念
C(Consistency,一致性)
数据在任何时刻、任何分布式节点中所看到的都是符合预期的。
一致性不是一个固定统一的概念,它在不同的分布式研究中有多种细分类型,但在每种类型中有严肃定义。
简单理解:所有服务器在同一时刻看到的数据都是相同且正确(符合预期)的。
A(Availability,可用性)
代表系统不间断提供服务的能力。
有两个指标与其密切相关:可靠性(Reliability)和可维护性(Serviceability)。
可靠性(Reliability):用平均无故障时间(Mean Time Between Failure,MTBF)来度量;
可维护性(Serviceability):用平均修复时间(Mean Time To Repair,MTTR)来度量。
可用性衡量系统正常使用和总使用时间之比,其表征为A=MTBF/(MTBF+MTTR),即可用性是由可靠性和可维护性计算得到的比例值,例如可用性为99.9999%,代表一年平均故障修复时间为32s。
简单理解:衡量故障的两个数值。可靠性:多久不发生一次故障,可维护性:发生故障后的修复时间。
P(Partition Tolerance,分区容忍性)
分布式网络中部分节点因网络原因而彼此失联后,即与其他节点形成“网路分区”时,系统仍能正确地提供服务的能力。
简单理解:部分服务器掉线后,剩下的服务器仍能为整个系统提供服务。
三、案例
以网络购物为例,通常要涉及三个集群——用户、商家、仓库(这里为简化模型,实际情况要复杂得多)。
每个集群又包含若干节点,例如用户集群包含节点1-10,这些节点为用户购物提供冗余服务,避免某个节点不可用引发的付款失败问题。。
当用户通过用户节点1花100元在商家2处购买了商品,它除了要给自己账户扣减100元之外,还要把交易变动告知其他用户节点、商家、仓库,以正确修改关联数据。
此时:
1)如果该变动没有告知其他账号节点,会导致用户购买另一件商品,被分配到另一个节点处理,该节点会由于看到不正确的账户余额从而错误发生了原本无法进行的交易,此为一致性;
2)如果要修复1)中的问题,把变动信息同步给其他账号节点,必须暂时停止对该用户的交易服务,直到数据同步一致后再恢复,此时会导致系统下一次购买商品时,由于系统暂时无法提供服务而拒绝交易,此为可用性问题;
3)如果由于集群中部分节点发生网络故障,无法正常与另一部分节点交换账号变动信息,那么服务集群中无论哪一部分节点对外提供服务可能都是不正确的,整个集群能否承受部分节点之间的连接中断而仍能正确提供服务,此为分区容忍性。
以上还仅仅涉及了账号服务器集群自身的CAP问题,对于整个站点来说,它还面临来自账号、商家、仓库服务集群带来的CAP问题。
四、放弃某个特性的影响
分区(网络不互联)
1)放弃分区容忍性P(保留CA)
意味着我们假设节点间通信永远可靠。永远可靠在分布式系统中必定不成立,只要用网络来共享数据,分区就一定存在。
现实中,最容易找到的放弃分区容忍性的例子就是关系数据库集群,这种集群虽然采用由网络连接的多个节点来协同工作,但数据并不通过网络来实现共享。以Oracle的RAC集群为例,它的每一个节点均有自己独立的SGA、重做日志、回滚日志等部件,但各个节点是通过共享存储中的同一份数据文件和控制文件来获取数据,通过共享磁盘来避免出现网络分区。因此Oracle RAC虽然也是由多个实例组成数据库,但是不能称为分布式数据库。
2)放弃可用性(保留CP)
意味着我们假设一旦网络发生分区,节点间的信息同步时间可以无限制延长。
在现实中,选择放弃可用性的CP系统一般用于对数据质量要求很高的场合,除了DTP模型的分布式数据库服务外,HBase也是CP系统。以HBase为例,当集群中某个区服务器宕机,这个区服务器持有的所有键值范围都要离线,直到数据恢复完成,这个过程要耗费的时间是无法估计的。
3)放弃一致性(保留AP)
意味着我们假设一旦网络发生分区,节点间提供的数据可能不一致。
选择放弃一致性是目前设计分布式系统的主流选择,因为P是分布式网络天然的属性(即使你不想要也没法丢弃),A是分布式的目的(如果可用性随节点数量增加而降低,那分布式系统就失去了存在价值)。
除了银行、证券这些对金钱敏感的服务,宁可中断也不能出错,否则多数系统是不能容忍节点越多可用性越低。目前大多数NoSQL和分布式缓存框架都是AP服务,以Redis集群为例,如果某个Redis出现网络分区,那么不妨碍各个节点以自己本地存储的服务对外提供缓存服务,但这时有可能出现请求分配到不同节点时给客户端返回不一致的数据。