数据一致性问题

1.数据库数据的正确性

事务的ACID四个特性保证了一个事务的正确性。

1.原子性,简单来说就是一件事,做完或者不做,不会有中间中断的情况发生。一旦发生错误,就回到开始之前的状态。

2.一致性,在事务开始之前和结束之后,数据完整性不被破坏。

3.隔离性,允许并发事务对数据同时进行读写。防止多个事务交叉执行而导致数据不一致。事务隔离分为读未提交、读提交、可重复读和串行化。

4.持久性,事务一旦完成,对数据的修改就是永久的,即便系统故障也不会丢失。

ACID的应用场景是数据库事务,是针对并发事务对数据库数据一致性的保证。

2.分布式系统数据的一致性

分布式系统数据的一致性,与ACID中的一致性并不一样。这里的一致性实际上是冗余副本,而在ACID中指的是数据库从一个一致性状态,在一个业务处理过后到达另外一个一致性状态,是为了达到另一个一致性状态而限制的业务约束,并没有副本的概念。

CAP理论中的描述:对一个分布式系统中,当涉及读写操作时,只能保证一致性、可用性、分区容错性,三者中的两个,另外一个必须被牺牲。这里面的C(一致性)实际上保证的是对于一个客户端而言,每一次的读操作,返回的一定是最新的写操作的结果。因为在一个事务处理过程中,分布式中每一个节点所拥有的数据是动态的并不会完全一致。对于客户端而言,读到的一定是读提交级别的数据或是事务失败回滚的初始数据。A(可用性)是指非故障的节点在合理的时间内返回合理的响应。P(分区容错性)是指当出现网络分区后,系统能够继续“履行职责”。

CAP与ACID的不同之处在于关注点不同,它关注的粒度是数据,而不是整个系统。

现在的对于CAP的应用主要分为了AP、CP两种,因为对于分布式而言P(分区容错性)是必选的,如果我们选择CA(一致性、可用性)发生分区现象时,由于网络的不可靠性,为了保证一致性我们一定会在在分区时禁止写入,就与可用性有了冲突。

CP,即网络分区时为了保证一致性,在客户端访问到数据未同步到最新的节点时会返回error。也就是暂时放弃了可用性的要求。AP,即网络分区出现时,在客户端访问到数据未同步到最新的节点时会返回旧的数据给他,暂时放弃了一致性的要求。在数据一致之后再用后续的方案进行数据筛选。

无论是CP还是AP都不应该在整个系统的角度去选择,因为就每个业务而言,数据或用户都是不同的。而且对于分区容错性而言,前提是要出现“网络分区”的情况,才会考虑放弃A或C的一种。而对于99.99%或99.999%可用性的系统而言一年中不可用时间是很短暂的。

3.BASE

base是指基本可用、软状态、最终一致性,核心思想是即使无法做到强一致性,但应用可以采用适合的方式达到最终一致性。

1.基本可用,系统在出现故障时,允许损失部分可用性,即保证核心功能可用。

2.软状态,允许系统存在中间状态,而该中间状态不会影响系统整体可用性。

3.最终一致性,系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。

BASE是CAP理论中AP方案的延伸。因为延时是无法避免的。这就意味着完美的CP场景是不存在的。因此CAP中的CP方案,实际上也是实现了最终一致性。分区期间牺牲一致性,但分区故障恢复后,系统应该达到最终一致性。

4.Paxos算法

Paxos算法是基于消息传递且具有高度容错特性的一致性算法。目的是为了解决分布式环境下一致性的问题。

一致性算法的原则是假如在分布式系统中初始是各个节点的数据是一致的,每个节点都顺序执行系列操作,然后每个节点最终的数据还是一致的。对于多个节点间的通信一般分为:共享内存和消息传递两种,Paxos是基于消息传递的,所以前提是我们认为信道一定是可靠的,消息是不会被篡改的。它提供了一种分布式选举算法,Paxos一共4个角色:Client、Proposer、 Acceptor、Learner。算法过程分为:prepare阶段、Accept阶段。对于Proposer发出的提议至少收到半数接受回复后才取得了提议权,将带有Value的提议再次发出。而对于acceptor而言,同时收到请求后,之和最后收到消息的proposer通信,并保存最新的信息,后续收到后若pid小于以保存的则直接拒绝,并将以保存的p-v返回给通信者。

5.CAP理论

CAP理论

第一版解释:简单翻译为:对于一个分布式计算系统,不可能同时满足一致性(Consistence)、可用性(Availability)、分区容错性(Partition Tolerance )三个设计约束。

第二版解释:简单翻译为:在一个分布式系统(指互相连接并共享数据的节点的集合)中,当涉及读写操作时,只能保证一致性、可用性、分区容错性三者中的两个,另外一个必须被牺牲。

1.一致性

简单翻译为:对某个指定的客户端来说,读操作保证能够返回最新的写操作结果。

对于系统执行事务来说,在事务执行过程中,系统其实处于一个不一致的状态,不同的节点的数据并不完全一致client读操作能够获取最新的写结果,因为事务在执行过程中,client是无法读取到未提交的数据的,只有等到事务提交后,client才能读取到事务写入的数据,而如果事务失败则会进行回滚,client也不会读取到事务中间写入的数据。

2.可用性

简单翻译为:非故障的节点在合理的时间内返回合理的响应(不是错误和超时的响应)。

3.分区容忍性

简单翻译为:当出现网络分区后,系统能够继续履行职责

第一版用的是work,第二版用的是function

CAP应用

分布式环境下来思考,我们必须选择P(分区容忍)要素,因为网络本身无法做到100%可靠,有可能出故障,所以分区是一个必然的现象。如果我们选择了CA而放弃了P,那么当发生分区现象时,为了保证C,系统需要禁止写入,当有写入请求时,系统返回error(例如,当前系统不允许写入),这又 和A冲突了,因为A要求返回no errorno timeout。因此,分布式系统理论上不可能选择CA架构,只能选择CP或者AP架构。

CP

如下图所示,为了保证一致性,当发生分区现象后,N1节点上的数据已经更新到y,但由于N1N2之间的复制通道中断,数据y无法同步到N2N2节点上的数据还是x。这时客户端C访问N2时,N2需要返回Error,提示客户端C“系统现在发生了错误,这种处理方式违背了可用性(Availability)的要求,因此CAP三者只能满足CP

AP

如下图所示,为了保证可用性,当发生分区现象后,N1节点上的数据已经更新到y,但由于N1N2之间的复制通道中断,数据y无法同步到N2N2节点上的数据还是x。这时客户端C访问N2时,N2将当前自己拥有的数据x返回给客户端C了,而实际上当前最新的数据已经是y了,这就不满足一致性(Consistency)的要求了,因此CAP三者只能满足AP。注意:这里N2节点返回x,虽然不是一个正确的结果,但是一个合理的结果,因为x是旧的数据,并不是一个错乱的值,只是不是最新的数据而已。

CAP关注的粒度是数据,而不是整个系统。

CA之间的取舍可以在同一系统内以非常细小的粒度反复发生,而每一次的决策可能因为具体的操作,乃至因为牵涉到特定的数据或用户而有所不同。

但这句话是理解和应用CAP理论非常关键的一点。CAP理论的定义和解释中,用的都是systemnode这类系统级的概念,这就给很多人造成了很大的误导,认为我们在进行架构设计时,整个系统要么选择CP,要么选择AP。但在实际设计过程中,每个系统不可能只处理一种数据,而是包含多种类型的数据,有的数据必须选择CP,有的数据必须选择AP。而如果我们做设计时,从整个系统的角度去选择CP还是AP,就会发现顾此失彼,无论怎么做都是有问题的。

以一个最简单的用户管理系统为例,用户管理系统包含用户账号数据(用户ID、密码)、用户信息数据(昵称、兴趣、爱好、性别、自我介绍等)。通常情况下,用户账号数据会选择CP,而用户信息数据会选择AP,如果限定整个系统为CP,则不符合用户信息数据的应用场景;如果限定整个系统为AP,则又不符合用户账号数据的应用场景。

所以在CAP理论落地实践时,我们需要将系统内的数据按照不同的应用场景和要求进行分类,每类数据选择不同的策略(CP还是AP),而不是直接限定整个系统所有数据都是同一策略。

CAP是忽略网络延迟的。

这是一个非常隐含的假设,布鲁尔在定义一致性时,并没有将延迟考虑进去。也就是说,当事务提交时,数据能够瞬间复制到所有节点。但实际情况下,从节点A复制数据到节点B, 总是需要花费一定时间的。如果是相同机房,耗费时间可能是几毫秒;如果是跨地域的机房,例如北京机房同步到广州机房,耗费的时间就可能是几十毫秒。这就意味着,CAP理论中的C在实践中是不可能完美实现的,在数据复制的过程中,节点A和节点B的数据并不一致。

对于某些严苛的业务场景,例如和金钱相关的用户余额,或者和抢购相关的商品库存,技术上是无法做到分布式场景下完美的一致性的。而业务上必须要求一致性,因此单个用户的余额、单个商品的库存,理论上要求选择CP而实际上CP都做不到,只能选择CA。也就是说,只能单点写入,其他节点做备份,无法做到分布式情况下多点写入。

需要注意的是,这并不意味着这类系统无法应用分布式架构,只是说单个用户余额、单个商品库存无法做分布式,但系统整体还是可以应用分布式架构的。例如,下面的架构图是常见的将用户分区的分布式架构。

 

我们可以将用户id0 ~ 100的数据存储在Node 1,将用户id101 ~ 200的数据存储在Node 2Client根据用户id来决定访问哪个Node。对于单个用户来说,读写操作都只能在某个节点上进行;对所有用户来说,有一部分用户的读写操作在Node 1上,有一部分用户的读写操作在Node 2上。

这样的设计有一个很明显的问题就是某个节点故障时,这个节点上的用户就无法进行读写操作了,但站在整体上来看,这种设计可以降低节点故障时受影响的用户的数量和范围,毕竟只影响20%的用户肯定要比影响所有用户要好。这也是为什么挖掘机挖断光缆后,支付宝只有一部分用户会出现业务异常,而不是所有用户业务异常的原因。

正常运行情况下,不存在CPAP的选择,可以同时满足CA

CAP理论告诉我们分布式系统只能选择CP或者AP,但其实这里的前提是系统发生了分区现象。如果系统没有发生分区现象,也就是说P不存在的时候(节点间的网络连接一切正常),我们没有必要放弃C或者A,应该CA都可以保证,这就要求架构设计的时候既要考虑分区发生时选择CP还是AP,也要考虑分区没有发生时如何保证CA

同样以用户管理系统为例,即使是实现CA,不同的数据实现方式也可能不一样:用户账号数据可以采用消息队列的方式来实现CA,因为消息队列可以比较好地控制实时性,但实现起来就复杂一些;而用户信息数据可以采用数据库同步的方式来实现CA,因为数据库的方式虽然在某些场景下可能延迟较高,但使用起来简单。

放弃并不等于什么都不做,需要为分区恢复后做准备。

CAP理论告诉我们三者只能取两个,需要牺牲sacrifced)另外一个,这里的牺牲是有一定误导作用的,因为牺牲让很多人理解成什么都不做。实际上,CAP理论的牺牲只 是说在分区过程中我们无法保证C或者A,但并不意味着什么都不做。因为在系统整个运行周期中,大部分时间都是正常的,发生分区现象的时间并不长。例如,99.99%可用性(俗称49)的系统,一年运行下来,不可用的时间只有50分钟;99.999%(俗称59)可用性的系统,一年运行下来,不可用的时间只有5分钟。分区期间放弃C或者A,并不意味着永远放弃CA,我们可以在分区期间进行一些操作,从而让分区故障解决后,系统能够重新达到CA的状态。

最典型的就是在分区期间记录一些日志,当分区故障解决后,系统根据日志进行数据恢复,使得重新达到CA状态。同样以用户管理系统为例,对于用户账号数据,假设我们选择了CP,则分区发生后,节点1可以继续注册新用户,节点2无法注册新用户(这里就是不符合A的原因,因为节点2收到注册请求后会返回error),此时节点1可以将新注册但未同步到节点2的用户记录到日志中。当分区恢复后,节点1读取日志中的记录,同步给节点2,当同步完成后,节点1和节点2就达到了同时满足CA的状态。

而对于用户信息数据,假设我们选择了AP,则分区发生后,节点1和节点2都可以修改用户信息,但两边可能修改不一样。例如,用户在节点1中将爱好改为旅游、美食、跑步,然后用户在节点2中将爱好改为美食、游戏,节点1和节点2都记录了未同步的爱好数据,当分区恢复后,系统按照某个规则来合并数据。例如,按照最后修改优先规则将用户爱好 修改为美食、游戏,按照字数最多优先规则则将用户爱好修改为旅游,美食、跑步,也可以完全将数据冲突报告出来,由人工来选择具体应该采用哪一条。

BASE理论本质上是对CAP的延伸和补充,更具体地说,是对CAP中AP方案的一个补充。前面在剖析CAP理论时,提到了其实和BASE相关的两点:CAP理论是忽略延时的,而实际应用中延时是无法避免的。

这一点就意味着完美的CP场景是不存在的,即使是几毫秒的数据复制延迟,在这几毫秒时间间隔内,系统是不符合CP要求的。因此CAP中的CP方案,实际上也是实现了最终一致性,只是一定时间是指几毫秒而已。

AP方案中牺牲一致性只是指分区期间,而不是永远放弃一致性。

这一点其实就是BASE理论延伸的地方,分区期间牺牲一致性,但分区故障恢复后,系统应该达到最终一致性。

综合上面的分析,ACID是数据库事务完整性的理论,CAP是分布式系统设计理论,BASECAP理论中AP方案的延伸。

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值