数据库&分布式-ACID & CAP/BASE
事务机制ACID和CAP理论是数据管理和分布式系统中两个重要的概念,很不巧,这两个概念中都有相同的“C”代表 “Consistency” 一致性,但是实际上是完全不同的意义,下面是比较两个概念的不同之处。
事务(transaction)
事务(Transaction)是由一系列对系统中数据进行访问与更新的操作所组成的一个程序执行逻辑单元(Unit),狭义上的事务特指数据库事务。
-
事务的作用: 当多个应用程序并发访问数据库时,事务可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作相互干扰。
事务为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持数据一致性的方法。
ACID
ACID,是指数据库管理系统(DBMS)在写入或更新资料的过程中,为保证事务(transaction)是正确可靠的,所必须具备的四个特性:原子性(atomicity,或称不可分割性)、一致性(consistency)、隔离性(isolation,又称独立性)、持久性(durability)。
- Atomic原子性: 一个事务的所有系列操作步骤被看成是一个动作,所有的步骤要么全部完成要么一个也不会完成,如果事务过程中任何一点失败,将要被改变的数据库记录就不会被真正被改变。
- Consistent一致性: 事务的一致性是指事务的执行不能破坏数据库数据的完整性和一致性,一个事务在执行前后,数据库都必须处于一致性状态。换句话说,事务的执行结果必须是使数据库从一个一致性状态转变到另一个一致性状态,这是不同于CAP理论的一致性”consistency”.
- Isolated隔离性: 主要用于实现并发控制, 隔离能够确保并发执行的事务能够顺序一个接一个执行,通过隔离,一个未完成事务不会影响另外一个未完成事务。事务隔离级别越高,就越能保证数据的完整性和一致性,但同时对并发性能的影响也越大。
- Durable持久性: 事务的持久性又称为永久性,是指一个事务一旦提交,对数据库中对应数据的状态变更就应该是永久性的。即使发生系统崩溃或机器宕机等故障,只要数据库能够重新启动,那么一定能够将其恢复到事务成功结束时的状态。。很多人认为这意味着事务是持久在磁盘上,但是规范没有特别定义这点。
分布式事务
分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于分布式系统的不同节点之上。通常一个分布式事务会涉及对多个数据源或业务系统的操作。
CAP
CAP是分布式系统中进行平衡的理论,它是由 Eric Brewer发布在2000年。
- Consistent一致性: 同样数据在分布式系统中所有地方都是被复制成相同。
- Available可用性: 所有在分布式系统活跃的节点都能够处理操作且能响应查询,用户体验
- Partition Tolerant分区容错性: 在两个复制系统之间,如果发生了计划之外的网络连接问题,对于这种情况,有一套容错性设计来保证。
一般情况下CAP理论认为你不能同时拥有上述三种,只能同时选择两种,这是一个实践总结,当有网络分区情况下,也就是分布式系统中,你不能又要有完美一致性和100%的可用性,只能这在两者选择一个。在单机系统中,你则需要在一致性和延迟性latency之间权衡。
对于多数大型互联网应用的场景,主机众多、部署分散,节点故障、网络故障是常态,必须保证P;应用的目的是提供服务,因此通常也要保证A。既然要保证P和A,就只能不同程度的舍弃C,牺牲一些用户体验。严格来讲,部分应用的A也不必保证100%,因此,主流做法是首要保障P、在A和C之间取舍、重A轻C。
但是,对于金融服务,必须保证C;大规模金融服务几乎必然涉及网络分区,所以也要保证P;为了保证C、P,只能牺牲A(停止服务)。对于某些特殊的金融服务,需要7*24小时提供服务,则改为牺牲部分P(如单节点主从备份,故障切换),保障C、A。
两者C的区别
-
ACID中的一致性的定义是:一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。 也就是说:如果事务是并发多个,系统也必须如同串行事务一样操作。其主要特征是保护性和不变性(Preserving an Invariant),以转账案例为例,假设有五个账户,每个账户余额是100元,那么五个账户总额是500元,如果在这个5个账户之间同时发生多个转账,无论并发多少个,比如在A与B账户之间转账5元,在C与D账户之间转账10元,在B与E之间转账15元,五个账户总额也应该还是500元,这就是保护性和不变性。
- 如果说ACID的C是节点服务器的数据完整性,而CAP的一致性是分布式多服务器之间复制数据以取得这些服务器拥有同样的数据,这是一种分布式领域的一致性概念。 分布式领域中的一致性有的强弱之分,强一致性也就是指一旦有写操作写入任何一个服务器,立即在其他服务器之间同步复制新的数据,这样, 任何服务器上任何读操作总是能看到最近写入的新数据。如果不能立即看到最近写入的新数据,而可能过了一段时间才能看到,则属于弱一致性或最终一致性了。
强一致性: 强一致性分为由写实现一致性Consistency by writes、由读实现一致性Consistency by reads和由冲裁实现一致性Consistency by Quorum。 由写实现一致性:在写入数据同时,将数据复制到其他服务器上,读取任何一台都可以获得新的写入数据,复制数据是在写操作完成,读操作轻量。 由读实现一致性:写入一旦服务器后,不再复制,而是在读取时使用版本来协调复制(如vector clock算法),这样我们简化了写操作,而将负担加在读操作。 由冲裁实现一致性:如果写入时复制到其他2/3大多数服务器,读取时也是从2/3大多数服务器读取,读取这边负责解决哪个更新是最新结果,这在读操作和写操作之间分担了负载。
- 如果要在分布式系统中实现像ACID那样的事务机制,只有强一致性还是不够的,如果我们操作步骤顺序很重要,不可以中断或打乱,我们要么一起一次执行它们,如果并发执行这些操作步骤,无论怎么并发,也要如同它们是在独立执行,我们最终得到的结果总是相同的,这是一种更强的一致性:线性一致性linearizable consistency,类似ACID中的隔离层(serial isolation level)。 The CAP FAQ将CAP定理中的一致性定义为这种线性一致性或称为atomic原子一致性。一种比普通一致性更强的一致性,这也是大家又将ACID的C和CAP的C等同在一起的原因。ACID的C与CAP的C的关系类似精确与一致性的关系,如下图:
这种分布式的线性强一致性有两种实现方式:2PC两段提交和Paxos算法是常见两种。
通过2PC写入新数据需要经过两次来回,第一次请求commit,第二次才正式确认commit,在这两者之间过程中,所有服务器都会堵塞等待发起者发出整个事务成功还是失败的结果(只有发起者知道所有服务器的情况),如果失败,所有服务器返回之前状态,相当于写入数据失败,写入数据没有发生过一样。
而Paxos算法能够回避2PC的堵塞死锁等问题更好地实现服务器之间数据强一致复制,具体内容见:Paxos算法。也可参考比Paxos算法改进的Raft算法。
BASE
BASE定理是对CAP定理的延伸:即使无法做到强一致性(Strong Consistency),但应用可以采用适合的方式达到最终一致性(Eventual Consitency)。CAP中提到的一致性是强一致性,所谓“牺牲一致性”指牺牲强一致性保证弱一致性。 BASE是指基本可用(Basically Available)、软状态( Soft State)、最终一致性( Eventual Consistency)。
- 基本可用:出现故障的时候,允许损失部分可用性,即,保证核心可用。 如,电商大促时,为了应对访问量激增,部分用户可能会被引导到降级页面,服务层也可能只提供降级服务
- 软状态:允许系统存在中间状态,而该中间状态不会影响系统整体可用性。 软状态本质上是一种弱一致性,允许的软状态不能违背“基本可用”的要求。如,分布式存储中一般一份数据至少会有三个副本,允许不同节点间副本同步的延时(某些时刻副本数低于3)。
- 最终一致性:系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。 软状态的终极目标是最终一致性。如,分布式存储的副本数最终会达到稳定状态。
ACID和BASE的区别与联系
ACID是事务的四个基本性质,属于传统数据库常用的设计理念,追求强一致性模型,详见事务的ACID和四个隔离级别。BASE支持的是大型分布式系统,提出通过牺牲强一致性获得高可用性(与分区容错性)。
在分布式系统设计的场景中,通常系统组件对一致性的要求不同,对ACID和BASE的取舍也就不同。