特性与模型
CAP 特性定义
Consistency | 一致性
一致性又称为原子性或者事务性,对某个指定的客户端来说,读操作保证能够返回最新的写操作结果。一致性表示一个事务的操作是不可分割的,要不然这个事务完成,要不然这个事务不完成,不会出现这个事务完成了一半这样的情况,也就不会读取到脏数据。传统的 ACID 数据库是很少存在一致性问题的,因为数据的单点原因,数据的存取又具有良好的事务性,不会出现读写的不一致。
而在分布式系统中,经常出现的一个数据不具有一致性的情况是读写数据时缺乏一致性。比如两个节点数据冗余,第一个节点有一个写操作,数据更新以后没有有效的使得第二个节点更新数据,在读取第二个节点的时候就会出现不一致的问题出现。这里并不是强调同一时刻拥有相同的数据,对于系统执行事务来说,在事务执行过程中,系统其实处于一个不一致的状态,不同的节点的数据并不完全一致。
一致性强调客户端读操作能够获取最新的写操作结果,是因为事务在执行过程中,客户端是无法读取到未提交的数据的。只有等到事务提交后,客户端才能读取到事务写入的数据,而如果事务失败则会进行回滚,客户端也不会读取到事务中间写入的数据。
Availability | 可用性
可用性主要是指系统能够很好的为用户服务,不出现用户操作失败或者访问超时等用户体验不好的情况;所谓非故障的节点在合理的时间内返回合理的响应,而不是错误和超时的响应。这里强调的是合理的响应,不能超时,不能出错。注意并没有说正确的结果,例如,应该返回 Java 但实际上返回了 Go,肯定是不正确的结果,但可以是一个合理的结果。
可用性通常情况下可用性和分布式数据冗余,负载均衡等有着很大的关联。
Partition Tolerance | 分区容忍性
分区容忍性即指当出现网络分区后,系统能够继续履行职责。这里网络分区是指:一个分布式系统里面,节点组成的网络本来应该是连通的。然而可能因为一些故障,譬如节点间网络连接断开、节点宕机等,使得有些节点之间不连通了,整个网络就分成了几块区域,数据就散布在了这些不连通的区域中。好的分区容忍性要求能够使应用虽然是一个分布式系统,而看上去却好像是在一个可以运转正常的整体。比如现在的分布式系统中有某一个或者几个机器宕掉了,其他剩下的机器还能够正常运转满足系统需求,这样就具有好的分区容忍性。
分区容忍性的典型场景,譬如数据库有两个拷贝在两个不同的数据中心,当数据被写到一个数据中心的时候,他也一定要被写到另一个数据中心。那么现在假设网络中断了,这就是我们所说的网络分区的意思:
我们可以有如下的两种策略:
-
应用还是被允许写到数据库,所以两边的数据库还是完全可用的。但是一旦两个数据库之间的网络中断了,任何一个数据中心的写操作就不会在另一个数据中心出现,这就违反了一致性。
-
如果你不想失去一致性,你就必须保证你的读写操作都在同一个数据中心,即 Leader 或者 Master 节点。另一个数据中心,因为网络故障不能被更新,就必须停止接收读写操作,直到网络恢复,两边数据库又同步了之后。所以虽然非 Leader 的数据库在正常运行着,但是他却不能处理请求,这就违反了可用性定义。
CAP 模型实践
实际应用中的可用性和 CAP 可用性并不相同。你应用的可用性多数是通过 SLA 来衡量的(比如 99.9%的正确的请求一定要在一秒钟之内返回成功),但是一个系统无论是否满足 CAP 可用性其实都可以满足这样的 SLA。实际操作中,跨多个数据中心的系统经常是通过异步备份(Asynchronous Replication)的,所以不是可线性化的。但是做出这个选择的原因经常是因为远距离网络的延迟,而不是仅仅为了处理数据中心的网络故障。
互联网行业模型。不同的业务类型要求不同的 CAP 模型,CA 适用于支付、交易、票务等强一致性的行业,宁愿业务不可用,也不能容忍脏数据。互联网业务对于强一致性不高,发个帖子要审核,没人看到无所谓。发一个音频要进行编码审核才能看到。
CA 模型
CA 模型即保证了可用性与强一致性,牺牲了分区容忍性。比如 MySQL Cluster 集群,提供两阶段提交事务方式,保证各节点数据强一致性。MySQL 的集群无法忍受脱离集群独立工作,一旦和集群脱离了心跳,节点出问题,导致分布式事务操作到那个节点后,整个就会失败,这是分区容忍性的牺牲。
当发生分区现象时,为了保证一致性,系统需要禁止写入。当有写入请求时,系统返回 Error(例如,当前系统不允许写入),不过这就又和可用性相冲突,因为可用性要求不可以返回错误或超时。因此分布式系统理论上不可能选择 CA 模型。
CP 模型
CP 模型即选择了强一致性与分区容忍性,牺牲了可用性。假设系统中存在节点 Node1 与 Node2,因为 Node1 节点和 Node2 节点连接中断导致分区现象,Node1 节点的数据已经更新到 y,但是 Node1 和 Node2 之间的复制通道中断,数据 y 无法同步到 Node2,Node2 节点上的数据还是旧数据 x。这时客户端 C 访问 Node2 时,Node2 需要返回 error,提示客户端系统现在发生了错误,这种处理方式违背了可用性的要求,因此 CAP 三者只能满足 CP。
CP 模型譬如 Redis 客户端 Hash 和 Twemproxy 集群,各 Redis 节点无共享数据,所以不存在节点间的数据不一致问题。其中节点宕机了,都会影响整个 Redis 集群的工作。当 Redis 某节点失效后,这个节点里的所有数据都无法访问。如果使用 3.0 Redis Cluster,它有中心管理节点负责做数据路由。
AP 模型
AP 模型牺牲了一致性,譬如同样是 Node2 节点上的数据还是旧数据 x,这时客户端 C 访问 Node2 时,Node2 将当前自己拥有的数据 x 返回给客户端了。而实际上当前最新的数据已经是 y 了,这就不满足一致性(Consistency)的要求了,因此 CAP 三者只能满足 AP。
值得一提的是,这里 Node2 节点返回 x,虽然不是一个正确的结果,但是一个合理的结果,因为 x 是旧的数据,并不是一个错乱的值,只是不是最新的数据。
譬如在 Cassandra 集群时,数据可以访问,数据能备份到各个节点之间,其中一个节点失效的话,数据还是可以出来的。而分布式事务的各个节点更新了提交了只是其中一部分节点,底层继续同步,这是 AP 模型。