女主宣言
1998年,加州大学的计算机科学家 Eric Brewer 提出分布式系统有三个指标,即CAP,而这三个指标不能同时做到。今天小编就为大家分享分布式相关理论,希望能对大家有所帮助。
PS:丰富的一线技术、多元化的表现形式,尽在“360云计算”,点关注哦!
1
前言
CAP、BASE、最终一致性是NoSQL数据库的三大理论基石。
2
CAP理论
CAP理论是一个非常知名的理论。在进行分布式系统设计的时候,我们一定会涉及到三个方面的性质。哪三个方面呢?
C: 一致性(Consistency)。指任何一个读操作总能读到之前完成的写操作的结果。也就是说在我们分布式环境中,多点的数据必须是一致的。所有节点在同一时间要具有相同的数据。
A: 可用性(Availability)。指快速的获取数据,可以在确定时间内返回操作结果,保证每个请求不管成功还是失败都有响应。
P: 分区容忍性(Partition tolerance)。指当网络出现分区的情况(即系统中的一部分节点无法和其他节点进行通信)分离的系统也能够正常运行。即:系统中任意信息丢失不会影响系统正常运作。
我们理想的目标是:希望设计一个分布式系统能够同时满足CAP。但是理论和实践都证明,这是不可能的,鱼和熊掌不可兼得。只能三者取其二,必须要牺牲一个性质,来成就另外两个性质。
CAP Theorem
牺牲一致性换取可用性的实例
假如在网络上有两台机器,M1和M2,两个机器上各跑一个进程,且初始值都是val0。
在M1这台机器上有个P1进程对副本V1进行了更新操作(副本V1在M1上,副本V2在M2上,为一个数据的两个副本)。在M1上P1对副本进行了更新,更新要传播到机器M2上面,传播完成之后,进程P2就要从副本V2中把更新读出来。
这样,进行P1在M1上写入一个数据,我们P2就可以在M2机器上把它读出来。就是在不同的位置写入,在另外一个位置读,数据是一致的,这是一致性。
如果网络发生故障,在中间环节,P1对数据进行更新,本来要传播到M2上,结果因为网络出现问题,无法传播。这个时候进程P2直接去读副本V2,你读到的肯定是不一致的数据。如果想马上读到副本的值,那你就要牺牲一致性(不管有没有值传过来,我要保证可用性,我要获取副本的值,即使副本的值是旧的)。此时,进程P2得到的就是不一致的值,虽然可以马上得到结果,满足可用性要求,但是牺牲了一致性。如果我想要一致性,那么P2进行就要一直等,等到数据能够传播到M2上,但是可能会过去很长时间,此时就是牺牲了可用性。
在面对CAP问题时有以下几种选择
CA:放弃分区容忍性,去成就可用性和一致性。把所有和事务相关的内容都放在一台机器上,避免网络分区。这样就根本不存在网络分区的问题,传统的关系数据库、集中式数据库,例如:Mysql、SQL Server,都是这种原则,因此他们的扩展性非常差。
CP:牺牲可用性,来成就一致性和分区容忍性。牺牲可用性含义就是:当出现网络分区的时候,我可以等数据一致后再去取数据,此时短时间内无法取到数据,失去可用性。
AP:放弃一致性,来成就可用性和分区容忍性。可及时获取数据,但是数据可能是不一致的。即使是不一致的,我也马上要这个数据。
不同产品在CAP理论下的不同设计原则
我们实际的设计当中,不同产品选择的设计方向不一样。比如,传统的MySQL、SQL Server就是放弃了它的分区容忍性。所以传统的MySQL都不会去做分区,就是放在一台机器上。Hbase、Redis是放弃了可用性,所以Hbase中的一些数据可能会有一定的延迟。
所以,不同的数据库在设计的时候,要考量的方向是不一样的。因此,公司在设计产品的时候要考虑到底要追求哪方面的特性,根据业务需求选择不同过的数据库产品特性。
3
BASE和最终一致性
BASE的定义
BASE是Basically Available Soft Sate和Eventual consistency的简写,意思是“碱”。
ACID是关系数据库中的事务的四个性质。在NoSQL数据库中BASE(碱)和ACID(酸)是对应的。
在关系型数据库中,追求的是ACID一致性。而在NoSQL数据库中追求的是BASE特性。
BASE的特性
基本可用(Basically Available):
指一个分布式系统的一部分发生问题变得不可用时,其他部分仍然可以正常使用,也就是允许分区失败的情况出现。例如:一个数据库系统部署了很多节点,有可能一两个节点出现了失败,但是整个系统依然是可用的
软状态(Soft State):
与硬状态是对应的,指状态可以有一段时间不同步,具有不同步的时间窗口,具有一定滞后性。
补充:
硬状态(Hard State):数据库状态必须一直保持数据库状态一致性,就是指任意时刻数据必须是正确的。
最终一致性(Eventual Consistency):
一致性的类型包括“强一致性”和“弱一致性”,两者的主要区别在于高并发的数据访问操作下,后续操作是否能够获取最新的数据。最终一致性是弱一致性的一种特例。
补充:
强一致性:一般要求,执行完一个更新之后,后续的其他操作都能够读到你更新的数据。
弱一致性:反之,执行一个更新操作之后,后续的读操作不能保证马上读到你刚写入的数据。
最终一致性
最终一致性为弱一致性的一种特例。根据更新数据后各进程访问到数据的时间和方式不同,可以区分为:
因果一致性:如果进程A通知进程B它已经更新了一个数据项,那么进程B的后续访问将获取进程A写入的最新值。比如,我通知你,你就能获取后面的更新值,其他进程C、D,我没有通知到你,你就访问不到我刚刚写的值,只能最终能访问到,不是马上就访问到。
读自己之所写:当进程A自己执行一个更新操作后,它自己总是可以访问更新过的值,不会看到旧值。
单调读一致性:如果进程已经看到过数据对象的某个值,那么任何后续访问都不会返回在那之前的旧值。
会话一致性:它把访问存储系统的这些进程,放到会话的上下文进程中,这个时候只要这些会话存在,系统就可以保证“读自己之所写一致性”。
单调写一致性:系统需保证来自同一进程的写操作按照顺序执行。同一个进程可能发生多个写操作,写操作有先有后,系统必须保证这些写操作,要按照顺序执行。
如何实现各种类型的一致性?
假设有一个分布式系统,为了实现它的可用性,要对数据进行冗余存储
N:数据的冗余份数。
W:更新数据时需要保证写完的节点数。例如,W=2,必须写入2个节点,才能保证更新数据顺利完成。
R:读取数据的时候需要读取的节点数。例如:R=2,只有保证读取了2节点数据,才能够完成这次读取。
在实际应用中是如何保证强一致性或者弱一致性的?
W+R>N :强一致性,因为写节点与读节点一定是重叠的,例如:对于典型的一主一备同步复制的关系型数据库。当N=2,W=2(当数据写完主库之后,再写完备库才返回),R=1(只要读取任意一个就返回)时,则不管是读主库还是备库的数据都是一致的。
W+R<=N:弱一致性,例如对一主一备异步复制的关系型数据库,N=2,W=1(写过主库,不管从是不是已经写了就返回),R=1(读主备任意一个库就返回),则如果读备库,就有可能无法读取主库已经更新过的数据。
N=W,R=1:强一致性,任何一个写节点失效都会导致写失败,因此可用性会降低,但是由于数据分布在N个节点,是同步写入的,因此可以保证强一致性。
因此,为了保证最低限度的强一致性,至少需要保证W+R=N+1。
对于分布式系统来讲,为了保证高可用(例如:HDFS),一般N>=3,至于W、R到底怎么取值,取决于不同的应用场景取舍和权衡。
实例
对于HBase数据库来说,HBase是借助底层的HDFS来实现其数据冗余备份。HDFS采用强一致性保证,在数据未完全同步到N个节点前,写操作不会成功返回,也就是说当W=N,而读操作只需要读到一个值即可,也就是说R=1。
对于Cassendra来讲,可以允许用户设置N、W、R的值,来达到用户的要求。
如果大家有什么建议或疑问,可以在下方留言交流。
360云计算
由360云平台团队打造的技术分享公众号,内容涉及数据库、大数据、微服务、容器、AIOps、IoT等众多技术领域,通过夯实的技术积累和丰富的一线实战经验,为你带来最有料的技术分享
来源:oschina
链接:https://my.oschina.net/u/4388188/blog/4559111