一. 什么是CAP(Consistency,Availability,Partition Tolerance)理论?
CAP理论认为任何分布式系统都不可能同时满足如下三个条件:
- Consistency(一致性保证):更新操作完成之后系统中所有节点的数据都应该完全一致,是强一致性要求。在实际系统中(尤其很多NoSQL系统中),常常会使用很多其他一致性模型,最经典的就是最终一致性,需要在此处区别。
- Avalability(可用性保证):对于用户的每一个读写请求,系统总是能够在一定时间内返回结果。
- Partition Tolerance(分区可容忍保证):系统在通信异常、信息丢失的情况下仍然可以正常工作。
CAP理论在98年提出并在02年被正式证明,在理论界产生了深刻的影响。随后,在工程领域作为指导性理论催生了一批优秀的分布式架构设计,包括Amazon的dynamo系统、FB的cassandra系统等。现在CAP理论已经被认为是NoSQL的基石,可见其影响一斑
那我们就会很好奇为什么CAP理论会有如此大的威力?
因为它为设计师们指明了一条路:不可能设计出一个系统可以同时满足一致性、可用性和分区可容忍性。但在实际分布式系统中,网络分区肯定会存在,所以任何系统都应该满足分区可容忍性,这样设计师们就只能在C和A之间选择一个。具体选择哪个,要根据具体的业务场景来定。一般来讲,NoSQL系统对一致性要求不是很高,会选择最终一致性模型保证系统的最终一致,这样就可以保证系统的可用性。而分布式数据库系统,尤其是金融数据库,对一致性要求很高,一般都会选择数据强一致性而放弃可用性保证。
二. 使用MySQL高可用方案解释CAP理论
既然CAP理论无论在理论界还是在工程界都如此重要,那接下来分析一下怎么理解CAP理论,为了方便理解,本人从MySQL高可用方案对CAP理论进行解释。
在解释CAP理论之前,需要先解释一下MySQL官方提供的两种高可用实例类型:异步复制类型和
同步复制类型
。
MySQL高可用采用Master-Slave架构,基于Binlog的复制功能实现,见下图:
一旦主上有事务提交,Master就会将事务写到Binlog并发送给Slave,Slave回放接收到的Binlog就可以得到一份和Master完全相同的数据。
对于异步实例(见下图)来讲,首先客户端提交请求给Master,Master在本机先Commit,完成之后就直接返回客户端OK。再异步的将Binlog发送给Slave,由Slave执行将数据同步。
而对于同步实例(见下图),客户端提交请求给Master之后,Master先将更新写到Binlog,发送给Slave,Slave Commit成功之后返回OK给Master,Master再Commit,成功之后返回给客户端OK。
好,可以根据上述背景知识分析CAP理论了:
1. 对于同步实例,在没有网络异常的情况下,在任何时刻用户的请求都可以正常完成,而且master和slave上的数据一致性可以得到保证。即,系统在AC得到保证的情况下,P无法得到保证。
2. 同样对于同步实例,如果网络出现异常,master和slave之间出现分区,用户的更新请求下发给master,master因为无法将binlog传给slave,就出现卡主现象,此时系统不可用。这种场景下系统在CP得到保证的情况下,A无法得到保证。
3. 而对于异步实例,即使在网络分区的情况下,客户端的请求一旦发送给master,master将更新操作写到binlog之后就可以立即返回,不需要等待slave的ack,所以系统一直是可用的。但是此时master和slave的数据明显会不一致。这种场景下系统在AP得到保证的情况下,C无法得到保证。
可见,系统只能同时保证CAP中的两个。
三. CAP Twelve Years Later
CAP理论的作者Eric Brewer后来又写过一篇文章:<<CAP twelve years later>>,在这篇论文中,作者提出了分区模式的概念,见下图:
他的原意是指,如果没有发生网络分区,整个系统可以同时保证C和A。一旦发生了分区,分区的两边依然可以同时保证C和A。但是从系统的角度看,就存在两个并行的一致性S1和S2。如果分区恢复正常,系统可以将S1和S2再次合并成一个一致性S'。
在RDS系统中并没有那么复杂的场景,但是分区模式的概念却很重要。要知道,在实际的分布式系统中,
网络分区发生的概率确实不大,因此可以换一种思路考虑系统的设计,如果我们能够检测到网络分区和网络分区恢复的话,可以在非网络分区时间段同时满足CA,再在网络分区时间段内选择CA中的某一个。
再以RDS为例讲解这种设计思路:
用户首先可以选择同步类型实例,在没有网络异常的情况下,系统可以同时保证用户关注的C和A。如果某一时刻不幸主从之间的网络出现了异常(RDS系统分区检测:复制延迟时间大于某一阈值,就认为网络出现分区),此时系统就应该进入分区模式。对于RDS实例来说,系统检测到网络分区之后就会将实例设为异步,牺牲掉一定时间段内的一致性,保证可用性,此时用户的读写操作都会正常得到响应。一旦系统检测到复制延迟时间小于某个阈值之后(认为网络分区恢复),会再次将实例设为同步状态,保证用户更加关注的CA特性。
因为网络分区发生的概率很小,所以大多数场景下系统都能够同时满足一致性和可用性,这对RDS系统开发者和用户来说都是最合理的结果。
总结:
这篇文章主要是结合RDS系统阐述了CAP理论,使大家对分布式系统设计有一个初步的了解,同时将分区模式的概念应用于RDS系统,实践与理论相结合。
本文来自网易实践者社区,经作者范欣欣授权发布。