从 paxos 到 zookeeper(二):从ACID到CAP/BASE

1.1简介

在上一篇文章中,我们讲解到集中式和分布式系统各自的特点,同时也看到了在从集中式架构到分布式架构变迁中碰到的一系列的问题。接下来将要看看分布式系统事务处理与数据一致性上遇到的种种挑战。

1.2 ACID

事务是由一系列对系统中数据进行访问与更新的操作所组成的一个程序执行逻辑单元,狭义上的事务特指数据库事务。一方面,当多个应用程序并发的访问数据库时,事务可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。另一个方面,事务为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持数据一致性的方法。
事务具有四个特征,分别是原子性(Atomicity),一致性(Consistency),隔离性(Isolation),和持久性(Durability)
原子性
事务的原子性是指事务必须是一个原子的操作序列单元。事务中包含的各项操作在一次执行过程中,只允许出现以下两种状态之一。
全部执行不成功
全部不执行
任何一项操作失败都将导致整个事务失败,同时其他已经被执行的操作都将被撤销并回滚,只有所有的操作全部成功,整个事务才算成功完成。
一致性
事务的一致性指的是事务的执行不能破坏数据库数据的完整性和一致性,一个事务在执行之前还是之后,数据库都必须处在一个一致性状态。也就是说事务的执行结果就是让数据库的状态从一个一致性状态变成另外一个一致性状态,因此当数据库只包含成功事务提交结果时,就说明数据库处在一致性状态。而如果数据库在运行过程中发生故障,有些事务尚未完成就被中断这些未完成的事务对数据库所做的修改有一部分已经写入物理数据库,这时数据库就处于在一种不正确的状态或者说数据不一致的状态。
隔离性
事务的隔离性是指在并发环境中,并发的事务是相互隔离的,一个事务的执行不能被其他的事务干扰。也就是说,不同的事务并发操作相同的数据时,每个事务都有各自完整的数据空间,即一个事务内部的操作及使用的数据也是对其他的并发事务是隔离的,并发执行各个事务之间不能相互干扰。
在标准SQL 规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同,如未授权读取,授权读取,可重复读取和串行化。
未授权读取
未授权读取也称为读未提交,该隔离级别别允许脏读取,其隔离级别最低。换句话说,如果一个事务正在处理某一数据,并对其进行了更新,但同时尚未完成事务,因此还没有进行事务提交;而与此同时,允许另一个事务也能够访问该数据。举个例子来说,事务A和事务B同时进行,事务A在整个执行阶段,会将某数据项的值从1开始,做一个系列加法操作(比如说加1操作)直到变成10之后进行事务提交,此时,事务B能够看到这个数据项在事务A操作过程中的所有中间值(如1变成2,2变成3等),而对这一系列的中间值的读取就是未授权读取
授权读取
授权读取也被称为读已提交,它和未授权读取非常相近,唯一的区别就是授权读取只允许读取已经被提交的数据。同样以上面的例子来说,事务A和事务B同时进行,事务A进行与上述同样的操作,此时事务B无法看到这个数据项在事务A操作过程中的所有中间值,只能看到最终的10.另外,如果说有一个事务C,和事务A进行非常类似的操作,只是事务C是将数据项从10加到20,此时事务B也同样可以读取到20,即授权读取允许不可重复读取。
可重复读取
可重复读取,简单的说就是保证在事务处理过程中,多次读取同一个数据时,其值都和事务开始时刻是一致性的。因此该事务级别禁止了不可重复读取和脏读取,但是有可能出现幻影数据。所谓幻影数据,就是指同样的事务操作,在前后两个事件段内执行对同一个数据项的读取,可能出现不一致的结果。对上面的例子,对可重复读取隔离级别能够保证事务B在第一次事务操作的过程中,始终对数据项读到的是1,但是在下一次事务的操作中,即使事务B采用同样的查询方式,就可能回读到10或者20.
串行化
串行化是最严格的事务隔离级别。他要求所有事务都被串行执行,即事务只能一个接一个地进行处理,不能并发执行。
事务隔离级别越高,越能保证数据的完整性和一致性,但是同时对并发性能的影响也越大。通常,对于绝大多数的应用程序来说,可以优先考虑将数据库的隔离级别设置为授权读取,这能够在避免脏读的同时能保证较好的并发性能。尽管这种事务隔离级别会导致不可重复读取,虚读和第二类丢失更新等并发问题,但较为科学的做法是在可能出现这类问题的个别场合中,由应用程序主动采用悲观锁或者乐观锁来进行事务控制。
持久性
事务的持久性也被称为永久性,是指一个事务一旦提交,它对数据库中对应数据的状态变更就应该是永久的。换句话说,一旦某个事务成功结束,那么它对数据库所做的变更就必须永久的保存下来-----即使发生系统崩溃或机器宕机等故障,只要数据库能够重新启动,那么一定能够将其恢复到事务成功结束时的状态
1.3分布式事务
随着分布式计算的发展,事务在分布式计算领域中也得到了广泛的应用。在单机数据库中我们很容易能够实现一套满足的ACID特性的事务处理系统,但在分布式数据库中,数据分散在各台不同的机器上,如何对这些数据进行分布式的事务处理具有非常大的挑战。在上一篇讲解了分布式环境中会碰到的种种问题,其中包括机器宕机和各种网络异常等。尽管存在着种种分布式问题,但是在分布式计算领域,为了保证分布式程序的可靠性,分布式事务是无法回避的。
分布式事务是指事务的参与者,支持事务的服务器,资源服务器以及事务管理器分别位于分布式系统的不同节点之上。通常一个分布式事务中会涉及对多个数据数据源或业务系统的操作。
我们可以设想一个最典型的分布式事务场景:一个跨银行的转账操作涉及调用两个异地的银行服务,其中一个是本地银行提供的取款服务,另一个则是目标银行提供的存款服务,这两个服务本身是无状态并且是互相独立的,共同构成了一个完整的分布式事务。如果从本地银行取款成功,但是因为某种原因存款服务失败了,那么就必须回滚到取款的状态,否则用户可能会发现自己的钱不翼而飞了。
从上面这个例子中,我们可以看到,一个分布式事务可以看作是由多个分布式的操作序列组成的,例如上面的例子中的取款服务和存款服务,通常可以把这一系列分布式的操作序列称为子事务。因此分布式事务也可以被定义为一种嵌套型的事务,同时也就具有了ACID事务特性。但由于在分布式事务中,各个子事务的执行是分布式的,因此要实现一种能够保证ACID特性的分布式事务处理系统就显得格外复杂。
1.4 CAP理论和BASE理论
对于本地事务处理或者是集中式的事务处理系统,很显然我们可以采用已经被实践证明很成熟的ACID模型来保证数据的严格一致性。而在上文中我们也已经看到,随着分布式事务的出现,传统的单机事务模型已经无法胜任。尤其是对于一个高访问量,高并发的互联网分布式系统来说,如果我们期望实现一套严格满足ACID的特性的分布式事务,很可能出现的情况就是在系统可用性和严格一致性之间出现冲突------因为当我们要求分布式系统具有严格的一致性时,很有可能就需要牺牲掉系统的可用性。但是毋庸置疑的一点是,可用性又是一个所有消费者不允许我们讨价还价的系统属性。比如说像淘宝网这样的在线购物网站,就要求它能够7乘以24小时不间断地对外提供服务,而对于一致性,则更加是所有消费者对于一个软件系统的刚需。因此,在可用性和一致性之间永远无法存在一个两全其美的方案,于是如何构建一个兼顾可用性和一致性的分布式系统成为了无数工程师的难题,出现了诸如CAP和BASE这样的分布式系统的经典理论。
CAP理论告诉我们,一个分布式系统不可能同时满足一致性,可用性,分区容错性这三个基本需求,最多只能同时满足其中两项。
一致性
在分布式环境中,一致性是指数据在多个副本之间是否能够保持一致的特性。在一致性的需求下,当一个系统在数据一致的状态下执行更新操作后,应该保证系统的数据仍然处于一致的状态
对于一个将数据副本分布在不同分布式节点上的系统来说,如果对第一个节点的数据进行更新操作并且更新成功后。却没有使得第二个节点上的数据得到更新。于是在读取第二个节点的数据,得到的依旧是老的数据。这个就是典型的分布式数据不一致的情况。在分布式系统中,如果能够做到针对一个数据项的更新操作执行成功后,所有用户都能读到最新的值,那么这样的系统就被认为具有强一致性。
可用性
可用性是指系统的服务必须一直处于可用的状态,对于用户的每一个操作请求能够在有限时间内返回结果。
分区容错性
分区容错性约束了一个分布式系统需要具有如下特性:分布式系统在遇到任何网络分区的故障的时候,仍然需要能够保证对外提供满足一致性可用性的服务,除非是整个网络环境都发生了故障。
网络分区是指在分布式系统中,不同的节点分布在不同的子网络中,由于一些特性的原因导致这些子网络之间出现网络不连通的情况,但各个子网络的内部网络正常的,从而导致整个系统的网络环境被切分成了若干个孤立的区域。
放弃P:如果能够避免系统出现分区容错性问题,一种是较为简单的将所有的数据都放在一个分布式节点上。这样的做法的保证系统不会出错,但至少不会碰到由于网格分区带来的负面影响。但是同时注意放弃P的同时就放弃了系统的可扩展性。
放弃A:相对于放弃分区容错性来说,放弃可用性则正好相反,其做法是一旦系统遇到网络分区或其他故障时,那么受到影响的服务需要等待一定的时间,因此在等待期间系统无法正常对外提供服务。
放弃C:这里说放弃一致性,并不是完全不需要数据一致性。要是那样的话那么系统的数据都将毫无意义。事实上,放弃一致性指的是放弃数据的强一致性,而保留数据的最终一致性。这样的系统无法保证数据保持实时一致性。但是可以承若的是数据最终能达到最终一直的状态。这个时候就引入了一个时间窗口的概念具体要多久才能达到一致。
从CAP理论中可以看出一个分布式系统不能同时满足一致性,可用性,和分区性这个三个要求。对于一个分布式系统分区容错性是必须的,因此再设计分布式系统中主要把精力根据业务如何权衡一致性和可用性。
BASE理论
BASE是Basically Available(基本可用),Soft state(软状态)和Eventually consistent(最终一致性)三个短语的简写。是基于CAP定理逐步演化而来的,其核心思想是即使无法做到强一致性,但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性。
基本可用
基本可用是指分布式系统在出现不可预知的故障时,允许损失一部分的可用性但不是等价于系统不可用。
**(1)响应时间损失:**正常情况下一个搜素引擎需要在0.5秒内返回结果给用户但是由于出现了故障这个时间增加到了1~2秒
**(2)功能上的损失:**正常情况下,在一个电子商务网站上购物时,消费者几乎能够顺利的完成每一笔订单,但是在一些节日大促购物高峰期的时候,由于消费者购物激增行为,为了保护购物系统的稳定性,部分消费者可能会被引导到一个降级页面
弱状态
弱状态也成为软状态,和硬状态相比相对,是指允许系统中的数据存在中间状态,并认为该状态的中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点之间进行数据同步的过程存在延时。
最终一致性
最终一致性强调的是系统中所有的数据副本,在进过一段时间后最终能够达到一个一致的状态,因此最终一致性的本质是需要系统保证最终数据能够达到一致而且不需要实时保证系统数据的强一致性
最终一致性最在下面5项变种
(1)因果一致性指如果进程A在更新完某个数据项后通知了进程B,那么进程B之后对该数据项的访问都应该能够获取到进程A更新的最新值,并且如果进程B要对该数据进行更新操作的话,务必基于进程A更新后的最新值即不能发生更新丢失的情况。与此同时与进程A无因果关系的进程C则没有这样的限制。
(2)读己之所写
读己之所写是指,进程A更新一个数据项之后,他自己总是能访问到更新过的最新值。因此读己之所写也是一种特殊的一致性
(3)会话一致性
会话一致性将系统数据的访问过程框定在了一个回话当中:系统能保证在同一个有效的回话中实现读己之所写的一致性,也就是说执行更新操作后,客户端能够在同一个回话中始终读到该数据项的最新值。
(4)单调读一致性
单调读一致性是指如果一个进程从系统中读取出一个数据项的某个值后那么系统对于该进程后续的任何数据访问都不应该返回更旧的值
(5)单调写一致性
单调写一致性是指:一个系统需要保证来自同一个进程的写操作被循序的执行
总的来说BASE 理论面向的是大型高可用可扩展的分布式系统,和传统的事务ACID特性是相反的,他完全不同于ACID的强一致性模型,而是提出通过牺牲强一致性来获得可用性,并允许数据在一段时间内不一致但最终达到一致性状态。但同时在分布式场景中,不同业务单元对数据的要求是不同的,因此具体的分布式系统架构设计的过程中,ACID特性与BASE理论又往往结合到一起了

猜你喜欢

转载自blog.csdn.net/u012957549/article/details/83869493