数据一致性
对于数据库而言,事务的ACID这4个特性保证了一个事务的正确性。其中,一致性特征是指在事务开始之前和结束之后数据完整性不被破坏。对于集中式系统而言,实现数据的一致性是容易的,毕竟依赖于数据库自然就实现了ACID特征。然而,在分布式系统中,要想保证数据的一致性就没有那么简单了。
本章介绍分布式系统下的数据一致性概念及解决方案。
什么是CAP理论
ACID的应用场景是数据库事务,是针对并发事务对数据库数据一致性的保证。然而在分布式系统中,通过使用副本的方式来保证系统的可用性及扩展性,这势必会引入一个重要问题,那就是数据的复制。对数据进行复制一般是为了增强系统的可靠性和提升性能。举例来说,当一个数据库的副本被破坏以后,那么系统只需要转换到其他数据副本就能继续运行下去。另外一个例子,当访问单一服务器管理的数据的进程数不断增加时,系统就需要对服务器的数量进行扩充,此时,对服务器进行复制,随后让它们分担工作负载,就可以提升性能。但复制数据的同时也带来了一个难点,那就是如何保持各个副本数据的一致性。换句话说,更新其中任意一个副本时,必须确保同时更新其他副本,否则,数据的各个副本将不再相同(数据不一致)。CAP理论的出现,让我们对于分布式事务的一致性有了另外一种看法。
CAP理论(也称为Brewer定理)是由计算机科学家Eric Brewer在2000年提出的,其理论观点是,在分布式系统中不可能同时提供以下3个保证。
·一致性(Consistency):所有节点同一时间看到的是相同的数据。
·可用性(Availability):不管是否成功,确保每一个请求都能接收到响应。
·分区容错性(Partition Tolerance):系统任意分区后,当网络故障时,仍能操作。
CAP定理如图17-1所示。
图17-1 CAP定理
在2003年的时候,Gilbert和Lynch就正式证明了这3个特征确实是不可以兼得的。Gilbert认为这里所说的一致性其实就是数据库系统中提到的ACID的另一种表述。
·一个用户请求要么成功要么失败,不能处于中间状态(Atomic)。
·一旦一个事务完成,将来的所有事务都必须基于这个完成后的状态(Consistent)。
·未完成的事务不会互相影响(Isolated)。
·一旦一个事务完成,就是持久的(Durable)。
对于可用性,其概念没有变化,指的是对于一个系统而言,所有的请求都应该“成功”并且收到“返回”。分区容错性就是指分布式系统的容错性。节点崩溃或者网络分片都不应该导致一个分布式系统停止服务。
为什么CAP只能三选二
下面分别举例说明为什么说CAP只能三选二。
图17-2显示了在一个网络中,N1和N2两个节点,它们都共享数据块V,其中有一个值V0。运行在N1的A程序可以认为是安全的、无Bug、可预测的和可靠的。运行在N2的是B程序。在这个例子中,A将写入V的新值,而B从V中读取值。
图17-2 示例一
系统预期执行下面的操作,如图17-3所示。
·首先写一个V的新值V1。
·然后消息(M)从N1更新V的副本到N2。
·现在,从B读取返回的V1。
图17-3 示例二
如果网络是分区的,当N1到N2的消息不能传递时,执行图17-4中的第3步,会出现虽然N2能访问到V的值(可用性),但其实与N1的V的值已经不一致了(一致性)的情况。
图17-4 示例三
CAP常见模型
CAP理论已经证明了分区容错性、可用性、一致性三者不可能同时达成,在实际应用中,可以在其中的某一些方面来放松条件,从而达到妥协。下面是常见的3种模型。
牺牲分区容错性(CA模型)
牺牲分区容错性意味着把所有的机器搬到一台机器内部,或者放到一个“要死大家一起死”的机架上(当然机架也可能出现部分失效),这明显违背了我们希望的可伸缩性。
CA模型常见的例子。
·单站点数据库。
·集群数据库。
·LDAP。
·xFS文件系统。
实现方式如下。
·两阶段提交。
·缓存验证协议。
牺牲可用性(CP模型)
牺牲可用性意味着一旦系统中出现分区这样的错误,系统直接就停止服务。
CP模型常见的例子。
·分布式数据库。
·分布式锁定。·绝大部分协议。
实现方式如下。
·悲观锁。
·少数分区不可用。
牺牲一致性(AP模型)
AP模型常见的例子。
·Coda。
·Web缓存。
·DNS。
实现方式如下。
·到期/租赁。
·解决冲突。
·乐观锁。