这篇文章着重点不在于科普,毕竟关于CAP、BASE的理论的文章,网上很多。所以本文科普篇幅尽量小(只包含概念描述)。主要从几个侧面的问题来描述CAP,进而描述ACID、BASE理念。然后加入一点点调料,如何动态的切换一致性强度。
本文通过以下几个问题,从侧面描述。文中个人观点较多,看官理性对待。
CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。这三个要素最多只能同时实现两点,不可能三者兼顾。
CAP定理中的可用性和一致性与用户感知的可用性和一致性不是一个概念。我们追求的应该是用户感知的可用性,CAP中可用性和一致性给我们只是起到指导性的作用。
2017 年,Google 公司的第一代 Spanner 系统已经诞生。Brewer 写了一篇文章讲述了 Google 公司的 Spanner 系统,并且近一步阐述了按照 CAP 定理 Spanner 是一个什么样特性的系统。在文中,Brewer 指出 Spanner 系统说是"实际上的 CA"(effectively CA)系统。从架构上来讲,Spanner 是一个 CP 系统,也就是说当出现网络分区时,Spanner 选择的是保证数据的一致性,放弃可用性的。但实际上,Spanner 是具有非常高可用性效果的一个系统,从架构上 Spanner 没有达到 CAP 定理要求的那种完全可用性,但是也达到非常高的可用性,由于采用多副本的设计,个别副本出现网络分区,并不影响用户能感知到的可用性。按 CAP 定理的定义,当这些个别副本出现网络分区时,这些节点是不可用的,也就是系统没有达到完全可用性。但是此时的用户请求是可以被其他副本服务的,此时服务是可用的,也就是说用户仍然感知到 Spanner 是可用的。所以说用户感知的可用性和 CAP 定理中的可用性不是一个概念。我们追求的应该是用户感知的可用性。
BASE是对一致性和可用性权衡所得的结果。其核心思想是:在某些场景中,无需做到强一致性,以保证系统的可用性,同时每个应用可以采用适当的方式使系统数据达到最终一致性。
BASE分别是指:Basically Available, Soft State, Eventual Consistency
对于ACID中一致性描述,可能理解都不一样,需要先统一下概念。
ACID中的C(一致性)的定义是:如果事务执行前数据库处于一致状态,那么当事务结束的时候,数据库也会处于一致性状态。这个一致性状态包含两层意思:
在分布式系统中,各个组建必然部署在不同的节点上,因此必然出现子网络,同时网络本身又是不可靠的,一定存在延迟和数据丢失,即网络分区是必然存在的。所以P(分区容错性)是分布式系统必须要面对和解决的问题(你无法要求在永远不发生网络分区的环境下运行分布式系统)。
因此CAP三者不可兼得,变成如何在C(一致性)、A(可用性)二者进行抉择,可以举个例子来说明:在分布式环境中,为了确保系统可用性,通常会采用将数据复制到多个备份节点,而复制的过程需要通过网络交互。当发生网络分区时,你将面临两个选择:
这里需要强调一句,CAP三者不可兼得,仅仅是指在发生网络分区情况下,我们才需要在A和C之间进行抉择,选择保证数据一致还是服务可用。而集群正常运行时,A和C是都可以保证的。
根据上一小节C、A二者不可兼得的原因,我们可以总结AP和CP架构的特性。可以发现CP、AP两者其实是对ACID、BASE的延伸。是在发生网络分区情况下ACID、BASE的表现。
ACID解决的问题是数据库系统中并发执行多个事务时的问题,是数据库领域的传统问题。那么多个事务并发会存在哪些问题?
为了解决这些问题,事务提出四种隔离级别来规避上述问题。而解决的就是ACID中的C(一致性),所以ACID中的C(一致性)可以理解为不出现脏读、幻读、不可重复读的问题。可以把它称为“内部一致性”,解决的是数据库内部的一致性问题。
CP中的C(一致性),相对好理解,我把它理解为“外部一致性”。就分布式系统而言的,针对客户端的请求,无论访问那个节点,都能获得最新的相同的值。
BASE强调的是基本可用,允许损失部分可用性。这里的损失是指:
AP则强调是高可用,对数据一致性要求更低。eureka作为AP系统的代表,在发生网络分区时,eureka会移除注册列表中长时间没有心跳的服务,但是当丢失过多客户端时,该节点会进入自我保护,将不会移除过期的服务,并同时接收新服务注册,但不会同步到其他节点。在该种模式下,eureka集群剩下最后一个节点,也可以向外提供服务。
描述AP和CP时,通常都会以eureka和zookeeper来具体。eureka是AP的代表作,zookeeper则是CP的代表作。二者之所以这样归类,是因为:
回答eureka没有放弃一致性的问题,还得回顾A、C之间的抉择。这二者需要二选一的情况下,一定是发生了网络分区的情况。eureka集群正常运行时,各节点之间可以正常通讯、保持心跳、复制数据,以此保持数据的一致性。但发生网络分区时,eureka确实选择了可用性,而放弃了一致性。
NWR是一种在分布式存储系统中用于控制一致性级别的一种策略。这个三个字母分别代表着:
NWR分别设置不同的值时,将会产生不同的一致性效果。
基于NWR的性质,我们可以动态的调节系统的一致性效果。还可以根据业务场景动态调整响应速度。以5节点集群为例,在保证强一致性的情况下,需要提高读请求的效率,则可以设置R=2、W=4或者R=1、W=5。当需要提高写请求效率时,则可以设置W=2、R=4或者W=1、R=5。
W、R的大小,直接影响其对应的处理效率。主要注意,读写请求的效率取决于最慢的副本处理速度。
CAP争论及历史:https://blog.csdn.net/chen77716/article/details/30635543
CAP,ACID,我们能做什么:http://hcoona.github.io/Tips/CAP-ACID-what-can-we-do/
理解数据库的事务,ACID,CAP和一致性:https://www.jianshu.com/p/2c30d1fe5c4e
nosql不应该放弃一致性:https://www.infoq.cn/article/rhzs0KI2G*Y2r9PMdeNv