起飞就起飞

数据一致性之三:CAP为啥无法同时达成?

Posted on By baixiao

再来细究一下 CAP 为啥无法同时达成?既然无法同时达成,总结一下各常见数据库分别适用其中哪两点:

必须优先满足P

中文叫做「分区容错」,必须优先满足。分布式系统是由若干台节点组成的一个网络,其中单台节点可能发生任何故障,包括:

  • OS重启
  • 硬盘故障
  • 和其他的节点网络失联(光纤损毁、内部交换机故障重启等等)

当然在 CAP 理论中,主要关注的故障情况是出现网络故障。什么情况下不会出现内部节点之间的网络故障?当只有一台物理机的时候😁。但这就不是分布式系统了。所以在设计分布式系统的时候,必须优先满足分区容错,不然单台节点发生意外之后就不可用了。

怎么理解满足「分区容错」?简单来说,就是当网络故障时,所有节点分成了两个集群,两个 client 分别连接到两个集群,要满足这两个 client 享受的服务一样,无论是读请求还是写请求。

C和A无法同时满足

假设数据库有两个拷贝在两个不同的数据中心。具体怎么做备份并不重要,可以是 Single-Master,或者多个 Leader,或者基于 Quorum 的备份(Dynamo 使用的方式)。要求是当数据被写到一个数据中心的时候,他也一定要被写到另一个数据中心。

假设 Client 只连接到其中一个数据中心,但是连接两个数据中心的网络故障了。现在面临两个选择:

  • 你的应用还是被允许写到数据库,所以两边的数据库还是完全可用的。但是一旦两个数据库之间的网络中断了,任何一个数据中心的写操作就不会在另一个数据中心出现。这就违反了一致性。
  • 如果你不想失去一致性,你就必须保证你的读写操作都在同一个数据中心,你可能叫它 Leader。另一个数据中心,因为网络故障不能被更新,就必须停止接收读写操作,直到网络恢复,两边数据库又同步了之后。所以虽然非 Leader 的数据库在正常运行着,但是他却不能处理请求,这就违反了 CAP 的可用性定义。

由此,在出现网络分区的时候,一致性和可用性只能满足其一。

RDBMS数据库表现怎么样?

对于 Single-Master 模型的关系型数据库,无论是 MySQL 或者 PostgreSQL,显然都不是 CAP 的。

  • 如果是同步备份的模型,在网络分区时,就不能再对 Master 写入数据,这就违反了可用性
  • 如果是异步备份的模型,在网络分区时,从 Slave 中读取的数据很可能不是最新版本,这就违反了一致性

所以难道说 RDBMS 数据库是 P 的(在网络分区的时候 Master 和 Slaver 分别可读)?这也说不通。只能说明 ACID 的概念和 CAP 南辕北辙,无法覆盖。

Redis集群怎么样?

Redis 原生集群发生网络分区时,

Cassandra呢?ZooKeeper呢?

ZooKeeper 要求达到大多数 Quorum,来达到共识,才能处理一个写操作。如果你有网络分区,一边有大多数节点,一边有少部分节点。那么拥有大多数节点的分区还可以继续工作,但是少部分节点的分区就算节点们都正常工作着,还是不能处理写操作。所以 ZooKeeper 的写操作在网络分区的情况下,不满足 CAP 的可用性。

参考

这可能是我看过最通俗也是最深刻的CAP理论