教程分类名称
关系型数据库是什么?
CAP理论是什么?
BASE原理与最终一致性
NoSQL数据库有哪些?
内存数据库是什么?
Redis是什么?
图形数据库是什么?
Neo4j数据库入门教程
TiDB数据库是什么?
文章导航
关系型数据库是什么?
CAP理论是什么?
BASE原理与最终一致性
NoSQL数据库有哪些?
内存数据库是什么?
Redis是什么?
图形数据库是什么?
Neo4j数据库入门教程
TiDB数据库是什么?
打开导航
# BASE原理与最终一致性 BASE 理论是针对 NoSQL 数据库而言的,它是对 [CAP](http://dandelioncloud.cn/view/6493.html) 理论中一致性(C)和可用性(A)进行权衡的结果,源于提出者自己在大规模分布式系统上实践的总结。其核心思想是无法做到强一致性,但每个应用都可以根据自身的特点,采用适当方式达到最终一致性。 ## 基本可用(Basically Available) 基本可用指分布式系统在出现故障时,系统允许损失部分可用性,即保证核心功能或者当前最重要功能可用。 对于用户来说,他们当前最关注的功能或者最常用的功能的可用性将会获得保证,但是其他功能会被削弱。 ## 软状态(Soft-state) 软状态允许系统数据存在中间状态,但不会影响系统的整体可用性,即允许不同节点的副本之间存在暂时的不一致情况。 ## 最终一致性(Eventually Consistent) 最终一致性要求系统中数据副本最终能够一致,而不需要实时保证数据副本一致。例如,银行系统中的非实时转账操作,允许 24 小时内用户账户的状态在转账前后是不一致的,但 24 小时后账户数据必须正确。 最终一致性是 BASE 原理的核心,也是 NoSQL 数据库的主要特点,通过弱化一致性,提高系统的可伸缩性、可靠性和可用性。而且对于大多数 Web 应用,其实并不需要强一致性,因此牺牲一致性而换取高可用性,是多数分布式数据库产品的方向。 最终一致性可以分为客户端和服务端两个不同的视角。 #### 从客户端的角度看 从客户端来看,一致性主要指的是多并发访问时更新过的数据如何获取的问题,最终一致性有以下 5 个变种。 | 一致性变种 | 说明 | | ------------------------------------- | ------------------------------------------------------------ | | 因果一致性 | 如果进程 A 通知进程 B 它已更新了一个数据项,那么,进程 B 的后续访问将返回更新后的值,且一次写入将保证取代前一次写入。与进程 A 无因果关系的进程 C 的访问遵守一般的最终一致性规则。 | | 读己之所写(Read-Your-Writes) 一致性 | 当进程 A 自己更新一个数据项之后,它总是访问到更新过的值,且不会看到旧值。这是因果一致性模型的一个特例。 | | 会话(Session)—致性 | 这是上一个模型的实用版本,它把访问存储系统的进程放到会话的上下文中。只要会话还存在,系统就保证“读己之所写”一致性。如果由于某些失败情形令会话终止,就要建立新的会话,而且系统保证不会延续到新的会话。 | | 单调(Monotonic)读一致性 | 如果进程已经看到过数据对象的某个值,那么任何后续访问都不会返回在那个值之前的值。 | | 单调写一致性 | 系统保证来自同一个进程的写操作顺序执行。 | 上述最终一致性的不同方式可以进行组合,例如,单调读一致性和“读己之所写”一致性就可以组合实现。从实践的角度来看,这两者的组合读取自己更新的数据,一旦读取到最新的版本,就不会再读取旧版本,对基于此架构上的程序开发来说,会减少很多额外的烦恼。 #### 从服务器的角度看 从服务端来看,如何尽快地将更新后的数据分布到整个系统,降低达到最终一致性的时间窗口,是提高系统的可用度和用户体验度非常重要的方面。 分布式数据系统有以下特性: - N 为数据复制的份数。 - W 为更新数据时需要进行写操作的节点数。 - R 为读取数据的时候需要读取的节点数。 如果 W+R>N,写的节点和读的节点重叠,则是强一致性。例如,对于典型的一主一备同步复制的关系型数据库(N=2, W=2,R=1),则不管读的是主库还是备库的数据,都是一致的。 如果 W+R≤N,则是弱一致性。例如,对于一主一备异步复制的关系型数据库(N=2,W=1,R=1),如果读的是备库,则可能无法读取主库已经更新过的数据,所以是弱一致性。 对于分布式系统,为了保证高可用性,一般设置 N≥3。设置不同的N、W、R 组合,是在可用性和一致性之间取一个平衡,以适应不同的应用场景。 如果N=W 且 R=1,则任何一个写节点失效,都会导致写失败,因此可用性会降低。但是由于数据分布的 N 个节点是同步写入的,因此可以保证强一致性。 如果 N=R 且 W=1,则只需要一个节点写入成功即可,写性能和可用性都比较高。但是读取其他节点的进程可能不能获取更新后的数据,因此是弱一致性。在这种情况下,如果 W<(N+1)/2,并且写入的节点不重叠,则会存在写冲突。