为什么你的高可用架构是个谎言(而且这没关系)

0 阅读6分钟

为什么你的高可用架构是个谎言(而且这没关系)

摘要: 本文挑战了数据库系统中关于“五个九”可用性和“零数据丢失”的常见神话,认为高可用架构建立在一致性、可用性和分区容忍性之间不可避免的权衡之上。作者使用 CAP 和 PACELC 定理为实际架构决策提供实用框架。

原文链接


如果达斯·维达存在,并决定对地球做他对阿尔德兰星做的事,每个人都会丢失数据。

我喜欢罗伯特·哈斯(Robert Haas)的这句话,因为这是我们都需要面对的现实检查。在数据库领域,我们不断被灌输“五个九”(99.999% 可用性)和“零数据丢失”(RPO[^1] 为 0)的梦想。我们花了数月时间构建复杂的集群来实现这一目标。

说实话:这些都是童话。想象中很美好,但在生产环境中并不存在。如果一把能毁灭星球的激光——甚至只是 一个糟糕的网络分区——击中你的数据中心,你的“保证”就会化为乌有。

我今天的目标不是帮你相信童话,而是帮你构建一个真正可行的架构。

CAP 定理:别再说“三选二”了

我看到一个非常常见的误解:你只需要在 CAP(一致性、可用性、分区容忍性)中“三选二”。

错了。

当没有网络分区时,你可以三者兼得!定理指出,在网络分区(P)期间,你被迫在一致性(C)和可用性(A)之间选择。当节点无法通信时,你无法同时保持两者。

就这样。这就是定理。

image.png图 1:CAP 定理——当没有分区时你可以三者兼得,但在分区期间必须选择

PACELC:CAP 没告诉你的事

CAP 告诉我们灾难期间发生了什么。它没有描述正常操作——当你的网络实际正常运行的时候。这就是 PACELC 的用武之地:

  • P(分区):如果存在网络分区,你必须在可用性或一致性之间选择。你无法两者兼得。
  • 否则:当没有分区时,你必须在延迟或一致性之间选择。你无法两者兼得。

image.png图 2:PACELC 通过在分区(左)和正常操作(右)期间都强制进行选择来扩展 CAP

在 PostgreSQL 中,PACELC 是你每个架构决策的地图。为了描述这些设置,我将使用 Dimitri Fontaine 的术语:女王(主节点/读写)、公主(备用节点)和 Worker(只读副本)。

案例研究 1:标准架构(异步复制)

KISS 配置:一个女王,一到两个公主,异步流复制。

CAP 视角:这是 AP。在分区期间,我们优先考虑可用性。我们将公主晋升为女王,这样应用程序就能继续运行,即使意味着丢失最近的一些事务。

PACELC 权衡:在正常操作期间(Else),我们优先考虑延迟(L)而不是一致性(C)。女王不等公主确认写入。速度快,但你要接受较小的 RPO(~200ms[^2])。

案例研究 2:“安全第一”(同步复制)

如果标准架构对你的 RPO 来说风险太大,请迁移到同步流复制。

CAP 视角:这更接近 CP,但不完全是。这里有一个误解:人们认为所有 RDBMS 都是 CP 系统。这只在单机 RDBMS 时才成立。一旦你添加复制,你就构建了一个分布式系统,而分布式系统无法纯粹是 CP。

为什么“更接近 CP”但不完全是?因为存在一个窗口,公主提交了事务但事务尚未在女王上提交。如果从公主读取,你得到的数据与从女王读取的数据不同。在该窗口期间,系统并非纯粹一致。

PACELC 权衡:在正常操作期间(Else),我们用延迟(L)换取一致性(C)。女王直到公主确认数据后才提交。你用潜在的数据丢失换取确定的延迟损失。

案例研究 3:高读取架构

当读取访问很关键时(例如医疗记录),添加多个 Worker。

配置:你有一个女王,一个同步公主(设置 synchronous_commit 和 quorum 为 1),以及多个 Worker。公主可以是任何备用节点——当时最快的节点会被加冕。PostgreSQL 会选择第一个确认写入的备用节点。这意味着你的“公主”角色可以根据网络条件和负载在节点之间切换。

Worker 提供读取可扩展性,而不影响写入延迟。

PACELC 权衡:我们优先考虑一致性(C)和读取可用性,以写入延迟(L)为代价。

案例研究 4:逻辑双向复制

对于需要在多个站点实现高写入可用性的全球企业,我们考虑逻辑双向复制。

PACELC 选择:分区期间实现最大可用性(A)。正常操作期间(Else),它优先考虑延迟(L)以实现跨地理区域的快速本地写入。

现实检查:这是最复杂的路径。选择 A 和 L 会带来巨大的复杂性和冲突管理挑战。原生 Postgres 复制是“天真的”——这是 Shaun Thomas 的话,不是我的。它缺乏复杂的冲突解决(通常是“最后更新胜出”,数据会被静默覆盖),并且如果违反约束会完全停止。

目前,能够实现这一“奇迹”的产品都是闭源的,不是免费的。

结论

设计数据库不是为了实现一个完美的神话设置,而是为了选择一种可接受的权衡。无论你是保护银行的交易还是医院的患者档案,最好的架构都承认失败是不可避免的。

遵循 KISS 原则:不要构建超过你需求的东西。法国人说“qui peut le plus peut le moins”(能做得更多的人也能做得更少),但在工程中这是一个糟糕的主意。“更多”在工程中意味着更多的复杂性、更多的成本、更多的故障模式,以及你不需要的头痛。

不要追求完美。为现实建模你的架构。


[^1]:RPO(恢复点目标):你能够承受的最大数据丢失量,以时间衡量。RPO 为 0 意味着零数据丢失。

[^2]:200ms 是同一本地网络服务器的典型复制延迟。虽然过去 5 年网络硬件有了显著改善,但这个数字仍然是一个安全的现实基准,因为数据库工作负载和写入量同比增长,使有效延迟保持在这个范围内。