Compute Engine 上 PostgreSQL 集群的高可用性架构

Last reviewed 2024-12-03 UTC

本文档介绍了多种可为 Google Cloud上的 PostgreSQL 部署提供高可用性 (HA) 的架构。高可用性用于衡量系统对底层基础架构故障的响应弹性。在本文档中,高可用性是指单个云区域内或多个区域之间的 PostgreSQL 集群的可用性,具体取决于高可用性架构。

本文档适合想要学习如何通过延长整体系统正常运行时间来提高 PostgreSQL 数据层可靠性的数据库管理员、云架构师和 DevOps 工程师。本文档讨论与在 Compute Engine 上运行 PostgreSQL 相关的概念。本文档未讨论如何使用 Cloud SQL for PostgreSQL 和 AlloyDB for PostgreSQL 等托管式数据库。

如果系统或应用需要持久状态来处理请求或事务,则必须使用数据持久层(数据层)才能成功处理针对数据查询或变更的请求。数据层中的停机时间会阻止系统或应用执行必要的任务。

根据系统的服务等级目标 (SLO),您可能需要一种能够提供更高可用性的架构。您可以通过多种方式来实现 HA,但一般而言,您可以预配能够很快供应用访问的冗余基础架构。

本文档讨论以下主题:

  • HA 数据库概念相关术语的定义。
  • 高可用性 PostgreSQL 拓扑选项。
  • 考虑每个架构选项的上下文信息。

术语

以下术语和概念是行业标准,有助于理解本文档以外的用途。

复制
一种过程,通过该过程,系统会可靠地捕获、记录写入事务(INSERT、UPDATE 或 DELETE)和架构更改(数据定义语言 (DDL)),然后将其依序应用于架构中的所有下游数据库副本节点。
主节点
为读取提供持久数据最新状态的节点。所有数据库写入都必须定向到主节点。
副本(辅助)节点
主数据库节点的在线副本。更改会从主节点同步或异步复制到副本节点。您可以从副本节点读取数据,但需要注意,由于复制延迟,数据可能会略微延迟。
复制延迟
以日志序列号 (LSN)、事务 ID 或时间来表示的一种量度。复制延迟表示更改操作应用于副本与应用于主节点之间的时间差异。
持续归档
一种增量备份方式,通过该方式,数据库持续将顺序事务保存到文件中。
预写式日志 (WAL)
预写式日志 (WAL) 是一个日志文件,它会在实际更改文件之前记录对数据文件的更改。如果服务器发生崩溃,WAL 是一种有助于确保写入数据完整性和耐用性的标准方法。
WAL 记录
应用于数据库的事务记录。WAL 记录会适当设置格式并存储为一系列描述数据文件页面级更改的记录。
日志序列号 (LSN)
事务会创建附加到 WAL 文件的 WAL 记录。插入的位置称为日志序列号 (LSN)。它是一个 64 位整数,由两个十六进制数字表示,用斜杠 (XXXXXXXX/YYZZZZZZ) 分隔。“Z”表示 WAL 文件中的偏移位置。
分段文件
包含尽可能多的 WAL 记录的文件,具体取决于您配置的文件大小。分段文件具有单调递增的文件名,默认文件大小为 16 MB。
同步复制
一种复制形式,在这种形式中,主服务器先等待副本确认已向副本事务日志写入数据,然后再确认向客户端提交。运行流式复制时,您可以使用 PostgreSQL synchronous_commit 选项,该选项有助于确保主服务器和副本之间的一致性。
异步复制
一种复制形式,在这种形式中,主服务器不会先等待副本确认已成功收到事务,然后再确认向客户端提交。与同步复制相比,异步复制具有更短的延迟时间。但是,如果主服务器崩溃并且其提交的事务没有传输到副本,则数据可能会丢失。异步复制是 PostgreSQL 上的默认复制模式,使用基于文件的日志传送或流式复制功能。
基于文件的日志传送
PostgreSQL 中的复制方法,用于将 WAL 分段文件从主数据库服务器传输到副本。主服务器以持续归档模式运行,而每个备用服务以持续恢复模式运行来读取 WAL 文件。此类复制是异步的。
流式复制
一种复制方法,其中副本连接到主服务器并持续接收一系列连续的更改。由于更新通过数据流到达,因此与日志传送复制功能相比,此方法可让副本与主服务器保持更为接近的状态。虽然复制默认是异步的,但您可以配置同步复制。
物理流式复制
将更改传输到副本的复制方法。此方法使用包含物理数据更改(磁盘块地址和逐个字节更改)的 WAL 记录。
逻辑流式复制
这种根据复制身份(主键)捕获更改的复制方法,可让您更好地控制数据复制方式(与物理复制相比)。由于 PostgreSQL 逻辑复制的限制,逻辑流式复制需要对高可用性设置进行特殊配置。本指南讨论标准物理复制,但不讨论逻辑复制。
uptime
资源运行且能够为请求提供响应的时间百分比。
故障检测
发现已发生基础架构故障的过程。
故障切换
将备份或备用基础架构(在本例中为副本节点)升级为主要基础架构的过程。在故障切换期间,副本节点会成为主节点。
切换
在生产系统上运行手动故障切换的过程。切换将测试系统是否运行良好,或者将当前的主节点从集群中移出进行维护。
恢复时间目标 (RTO)
完成数据层级故障切换过程的实时持续时间。RTO 取决于从商业角度来看可接受的时长。
恢复点目标 (RPO)
因故障切换而留存数据层级时的数据丢失量(以实时持续时间来表示)。RPO 取决于从商业角度来看可接受的数据丢失量。
后备
在解决导致故障切换的问题后恢复之前的主节点的过程。
自我修复
系统在没有人工操作员执行外部操作的情况下解决问题的能力。
网络分区
一个架构中的两个节点(例如主节点和副本节点)不能通过网络彼此通信时的情况。
脑裂
两个节点同时认为自己是主节点时发生的情况。
节点组
提供服务的一组计算资源。在本文档中,该服务是数据持久层。
见证或仲裁节点
一个单独的计算资源,帮助节点组确定在脑裂条件下要执行的操作。
主节点选举
一组对等感知节点(包括见证节点)确定哪个节点应作为主节点的过程。

何时考虑使用 HA 架构

与单节点数据库设置相比,HA 架构可提供更强的数据层级停机保护。如需为您的业务应用场景选择最佳选项,您需要了解您能够承受的停机时间以及各种架构各自的利弊。

如果您想提供更长的数据层正常运行时间以满足您的工作负载和服务的可靠性要求,则可以使用高可用性架构。如果您的环境能够容忍一定的停机时长,HA 架构可能会产生不必要的费用和复杂性。例如,开发环境或测试环境通常不需要较高的数据库层可用性。

考虑您的 HA 要求

以下若干问题可帮助您确定哪种 PostgreSQL HA 选项最适合您的企业:

  • 您想要达到哪种可用性级别?您是否需要某个选项让您的服务仅在单个可用区故障或整个区域故障期间继续运行?有些 HA 选项仅限于某个区域,而有些选项则适用于多区域。
  • 如果数据持久层出现停机,哪些服务或客户依赖于您的数据层?您的业务费用是多少?如果一项服务仅满足需要偶尔使用该系统的内部客户的需求,则其可用性要求可能会比面向最终客户的、持续为客户提供服务的服务的要求低。
  • 您的运营预算是多少? 费用是一个值得注意的考虑因素:为了提供高可用性,您的基础架构和存储费用可能会增加。
  • 该过程需要多么自动化,以及您需要多长时间进行故障切换?(您的 RTO 是什么?) 高可用性选项因系统可以进行故障切换的速度和对客户可用的速度而异。
  • 您是否能够承受故障切换所导致的数据丢失现象?(您的 RPO 是什么?)由于 HA 拓扑的分布式特性,您需要权衡提交延迟时间与数据因故障而丢失的风险。

高可用性的工作原理

本部分介绍基于 PostgreSQL 高可用性架构的流式和同步流式复制。

流式复制

流式复制是一种复制方法,即副本连接到主实例并持续接收 WAL 记录流。与日志传送复制功能相比,流式复制功能可让副本与主实例保持同步。从版本 9 开始,PostgreSQL 提供内置的流式复制功能。许多 PostgreSQL 高可用性解决方案都使用内置的流式复制功能,为多个 PostgreSQL 副本节点提供与主实例同步的机制。本文档后面的 PostgreSQL 高可用性架构部分介绍了其中一些选项。

每个副本节点都需要专用的计算和存储资源。副本节点基础架构与主实例无关。您可以将副本节点用作热备用服务器以处理只读客户端查询。此方法允许跨一个或多个副本进行只读查询负载均衡。

默认情况下,流式复制是异步进行的;主服务器不会先等待副本确认,然后再向客户端确认事务提交。如果主服务器在确认事务之后、副本收到事务之前发生故障,则异步复制可能会导致数据丢失。如果副本提升为新的主节点,则不会存在此类事务。

同步流式复制

您可以通过将一个或多个副本选择为同步备用节点,将流式复制配置为同步复制。如果您为同步复制配置架构,则在副本确认事务存在之前,主服务器不会确认事务提交。同步流式复制功能可实现更高的耐用性,从而增加事务延迟时间。

synchronous_commit 配置选项还可让您为事务配置以下渐进式副本耐用性保证:

  • local:同步备用副本不参与提交确认。主节点在将 WAL 记录写入并 flush 到本地磁盘后,确认事务提交。主节点上的事务提交不涉及备用副本。如果主节点出现任何故障,事务可能会丢失。
  • on [默认]:同步备用副本会在向主服务器发送确认消息之前将提交的事务写入其 WAL。使用 on 配置可确保只有在主服务器和所有同步备用副本同时发生存储故障时,事务才会丢失。由于副本仅在写入 WAL 记录之后才会发送确认消息,因此查询副本的客户端只有在相应的 WAL 记录应用于副本数据库后才会看到更改。
  • remote_write:同步备用副本会在操作系统级别确认收到 WAL 记录,但不保证 WAL 记录已写入磁盘。由于 remote_write 不保证 WAL 已写入,因此在写入记录之前,如果主实例和辅助实例出现任何故障,事务可能会丢失。remote_write 的耐用性低于 on 选项。
  • remote_apply:同步备用副本在确认向客户端提交事务之前会确认事务收据和成功的应用。使用 remote_apply 配置可以确保事务始终保存到副本,并且客户端查询结果立即包含事务的效果。与 on 和 remote_write 相比,remote_apply 具有更高的耐用性和一致性。

synchronous_commit 配置选项与 synchronous_standby_names 配置选项搭配使用,后者指定参与同步复制过程的备用服务器列表。如果未指定同步备用名称,则事务提交不会等待复制。

PostgreSQL HA 架构

最基本级别的数据层级 HA 包含以下方面:

  • 用于确定主节点故障是否出现的机制。
  • 执行将副本节点提升为主节点的故障切换的过程。
  • 更改查询路由以使应用请求到达新的主节点的过程。
  • (可选)使用故障切换之前具有原始容量的主节点和副本节点回退到原始架构的方法。

以下部分简要介绍了以下高可用性架构:

  • Patroni 模板
  • pg_auto_failover 扩展程序和服务
  • 有状态 MIG 和区域永久性磁盘

如果有基础架构或地区服务中断,这些高可用性解决方案可以最大限度地减少停机时间。选择这些选项时,根据您的业务需求平衡提交延迟时间和耐用性。

高可用性架构的一个关键方面是为后续故障切换或回退准备新的备用环境所需的时间和手动工作量。否则,系统只能应对一个故障,并且服务无法防范服务等级协议 (SLA) 违规。我们建议您选择能够使用生产基础架构执行手动故障切换或切换的 HA 架构。

使用 Patroni 模板实现 HA

Patroni 是一个成熟且积极维护的开源(MIT 许可)软件模板,可为您提供配置、部署和操作 PostgreSQL 高可用性架构的工具。Patroni 提供分布式集群状态和分布式配置架构,这些配置始终保留在分布式配置存储区 (DCS) 中。用于实现 DCS 的选项包括:etcd、Consul、Apache ZooKeeper 或 Kubernetes。下图显示了 Patroni 集群的主要组件。

Patroni 集群在 PostgreSQL 节点、DCS 和 Patroni 代理之间进行交互。

图 1.展示 Paroni 集群的主要组件示意图。

在图 1 中,PostgreSQL 节点、DCS 和 Patroni 代理前面的负载均衡器在 PostgreSQL 节点上运行。

Patroni 在每个 PostgreSQL 节点上运行代理进程。代理进程管理 PostgreSQL 进程和数据节点配置。Patroni 代理通过 DCS 与其他节点协调。Patroni 代理进程还会公开一个 REST API,您可以查询该 API 来确定每个节点的 PostgreSQL Service Health 和配置。

为了声明其集群成员角色,主节点会定期更新 DCS 中的领导者密钥。领导者密钥包含存留时间 (TTL)。如果 TTL 没有更新,则系统会从 DCS 中逐出领导者密钥,并且领导者选举机制会开始从候选池中选择新的主节点。

下图显示了一个运行状况良好的集群,其中节点 A 已成功更新领导者锁。

运行状况良好的集群领导者会更新领导者锁,而领导者候选者会观察到。

图 2:运行状况良好的集群图。

图 2 显示运行状况良好的集群:节点 A 成功更新领导者密钥时,节点 B 和节点 C 会观察到。

故障检测

Patroni 代理通过在 DCS 中更新密钥来持续通告其运行状况。同时,该代理会验证 PostgreSQL 运行状况;如果代理检测到问题,则会通过关停自身来避开节点或者将节点降级为副本。如下图所示,如果发生故障的节点是主节点,则 DCS 中的领导者密钥将到期,并且会触发新的领导者选举。

损坏的集群会在现有领导者密钥过期后选举新的领导者。

图 3.受损集群示意图。

图 3 显示了一个损坏的集群:已停机的主节点最近没有在 DCS 中更新其领导者密钥,并且非领导者副本得知领导者密钥已过期。

在 Linux 主机上,Patroni 还会在主节点上运行操作系统级监控定时器。此监控定时器会侦听 Patroni 代理进程中的 keep-alive 消息。如果该进程无响应,并且没有发送 keep-alive 消息,则监控定时器会重启主机。监控定时器有助于防止脑裂状况(其中 PostgreSQL 节点继续充当主节点,但 DCS 中的领导者密钥因代理故障而过期,并且其他主节点(领导者)已选出)。

故障切换过程

如果主要锁定会在 DCS 中过期,则候选副本节点将启动一连串选举。当副本发现缺少主要的锁时,会检查其复制位置与其他副本相比。每个副本使用 REST API 获取其他副本节点的 WAL 日志位置,如下图所示。

在 Patroni 故障切换过程中,副本会检查其在 WAL 日志中的位置。

图 4.展示 Patroni 故障切换过程的示意图。

图 4 显示 WAL 日志位置查询和来自活跃副本节点的相应结果。节点 A 不可用,运行状况良好的节点 B 和 C 互相返回同一 WAL 位置。

最新节点(如果节点位于同一位置)会同时尝试获取 DCS 中的领导者锁。但是,只有一个节点可以在 DCS 中创建领导者密钥。成功创建领导者密钥的第一个节点是领导者竞争的获胜者,如下图所示。 或者,您也可以通过在配置文件中设置 failover_priority 标记来指定首选故障切换候选实例。

某个节点在 DCS 中创建领导者密钥并成为新的主节点。

图 5.领导者竞争示意图。

图 5 显示领导者竞争:两个领导者候选者尝试获取领导者锁,但只有其中的一个节点(节点 C)成功设置了领导者密钥并赢得竞争。

在赢得领导者选举后,副本将自身提升为新的主节点。从副本提升自身之时开始,新的主节点会更新 DCS 中的领导者密钥以保留领导者锁,而其他节点则充当副本。

Patroni 还提供 patronictl 控制工具,可让您运行切换以测试节点的故障切换过程。 此工具有助于运维人员在生产环境中测试其高可用性设置。

查询路由

在每个节点上运行的 Patroni 代理进程公开了显示当前节点角色(主节点或副本节点)的 REST API 端点。

REST 端点 HTTP 返回代码(如果是主节点) HTTP 返回代码(如果是副本节点)
/primary 200 503
/replica 503 200

由于相关健康检查会在特定节点更改其角色时更改其响应,因此负载均衡器健康检查可以使用这些端点来通知主要和副本节点流量路由。Patroni 项目为 HAProxy 等负载均衡器提供模板配置。内部直通式网络负载均衡器可以使用这些相同的健康检查来提供类似的功能。

回退过程

如果节点发生故障,则集群会进入降级状态。Patroni 的回退过程有助于在故障切换后将高可用性集群恢复到健康状况良好的状态。回退过程通过自动将受影响的节点初始化为集群副本来管理集群恢复到原始状态的操作。

例如,节点可能会由于操作系统或底层基础架构发生故障而重启。如果节点是主节点并且需要比领导者密钥 TTL 更长的时间来重启,则会触发领导者选举,然后选择并提升新的主节点。当过时的主 Patroni 进程启动时,它会检测到没有领导者锁,然后自动将自身降级为副本并将集群加入该容量。

如果出现不可恢复的节点故障(例如不太可能发生的可用区故障),您需要启动新节点。数据库操作人员可以手动启动新节点,或者您可以使用节点数最小的有状态区域级托管式实例组 (MIG) 来自动执行该过程。创建新节点后,Patroni 会检测到新节点是现有集群的一部分,并自动将节点作为副本进行初始化。

使用 pg_auto_failover 扩展程序和服务实现 HA

pg_auto_failover 是主动开发的开源(PostgreSQL 许可)PostgreSQL 扩展程序。pg_auto_failover 通过扩展现有的 PostgreSQL 功能配置高可用性架构。pg_auto_failover 不具有 PostgreSQL 以外的任何依赖项。

要将 pg_auto_failover 扩展程序与 HA 架构搭配使用,您需要至少三个节点,每个节点运行已启用该扩展程序的 PostgreSQL。任何节点都可能出现故障,而不会影响数据库组的正常运行时间。由 pg_auto_failover 管理的节点集合称为结构。下图展示了 pg_auto_failover 架构。

pg_auto_failover 架构包含节点编队。

图 6.pg_auto_failover 架构图。

图 6 显示了 pg_auto_failover 架构,它由两个主要组件构成:Monitor 服务和 Keeper 代理。Keeper 和 Monitor 均包含在 pg_auto_failover 扩展程序中。

Monitor 服务

pg_auto_failover Monitor 服务作为 PostgreSQL 扩展程序实现;当服务创建 Monitor 节点时,它会启动一个启用了 pg_auto_failover 扩展程序的 PostgreSQL 实例。Monitor 会维护节点编队的全局状态,从成员 PostgreSQL 数据节点获取健康检查状态,并使用由有限状态机 (FSM) 建立的规则编排群组。根据状态转换的 FSM 规则,Monitor 将指令传达给组节点,以执行提升、降级和配置更改等操作。

Keeper 代理

在每个 pg_auto_failover 数据节点上,扩展程序会启动 Keeper 代理进程。此 Keeper 进程会观察和管理 PostgreSQL 服务。Keeper 会将状态更新发送到监控节点,并接收和执行监控功能发送的操作。

默认情况下,pg_auto_failover 将所有群组辅助数据节点设置为同步副本。提交所需的同步副本数量基于您在 Monitoring 中设置的 number_sync_standby 配置。

故障检测

主要和次要数据节点上的 Keeper 代理定期连接到 Monitor 节点以传达其当前状态,并检查是否执行任何操作。Monitor 节点还会连接到数据节点,以通过执行 PostgreSQL 协议 (libpq) API 调用并模拟 pg_isready() PostgreSQL 客户端应用来执行健康检查。如果这些操作在一段时间(默认为 30 秒)后均未成功,则监控节点会确定发生数据节点故障。您可以更改 PostgreSQL 配置设置以自定义监控时间以及重试次数。如需了解详情,请参阅故障切换和容错能力。

如果发生单节点故障,则会出现以下情况之一:

  • 如果健康状况不佳的数据节点是主节点,则 Monitor 会启动故障切换。
  • 如果运行状况不佳的数据节点是辅助节点,则 Monitor 会停用运行状况不佳的节点的同步复制。
  • 如果故障节点是 Monitor 节点,则系统无法自动执行故障切换。如需避免这种单点故障,您需要确保采取正确的监控和灾难恢复措施。

下图展示了前述列表所述的故障场景和节点编队结果状态。

主节点、辅助节点和监控节点故障的 pg_auto_failover 故障场景。

图 7.pg_auto_failover 故障场景图。

故障切换过程

组中的每个数据库节点都具有以下配置选项,用于确定故障切换过程:

  • replication_quorum:布尔值选项。如果 replication_quorum 设置为 true,则该节点会被视为潜在故障切换候选对象
  • candidate_priority:从 0 到 100 的整数值。candidate_priority 的默认值是 50,您可以更改该值以影响故障切换优先级。系统会根据 candidate_priority 值将节点视为潜在的故障切换候选对象。具有较高 candidate_priority 值的节点的优先级更高。故障切换过程要求任何 pg_auto_failover 结构中至少有一个节点具有非零候选优先级。

如果存在主节点故障,则当辅助节点具有活跃同步复制功能且属于 replication_quorum 成员时,系统会考虑将辅助节点提升为主节点。

根据以下渐进式条件,系统会考虑提升辅助节点:

  • 候选优先级最高的节点
  • 最高级的 WAL 日志位置已发布到 Monitor 的备用节点
  • 将随机选择的结果作为最终结果

如果故障切换候选者尚未在 WAL 中发布最高级的 LSN 位置,则该候选者会成为落后的候选者。在这种情况下,pg_auto_failover 会在故障切换机制中编排中间步骤:落后的候选者从具有最高级 LSN 位置的备用节点提取缺失的 WAL 字节。随后,系统会提升备用节点。Postgres 允许此操作,因为级联复制功能可以将任何备用节点用作另一个备用节点的上游节点。

查询路由

pg_auto_failure 不提供任何服务器端查询路由功能。pg_auto_failure 依赖于使用官方 PostgreSQL 客户端驱动程序 libpq 的客户端查询路由。当您定义连接 URI 时,驱动程序可以通过其 host 关键字接受多个主机。

应用使用的客户端库必须封装 libpq 或实现为架构提供多个主机的功能,以支持完全自动化的故障切换。

回退和切换过程

Keeper 进程重启失败的节点或启动新的替换节点时,该进程会检查 Monitor 节点以确定要执行的下一个操作。如果重启的故障节点原先是主节点,并且 Monitor 已经根据故障切换过程选择了新的主节点,Keeper 会将此过时的主节点重新初始化为辅助副本。

pg_auto_failure 提供了 pg_autoctl 工具,可让您运行切换以测试节点故障切换过程。除了让操作者在生产环境中测试其高可用性设置外,该工具还有助于在故障切换后将高可用性集群恢复到健康状况良好的状态。

使用有状态 MIG 和区域永久性磁盘实现 HA

本部分介绍了一种使用以下 Google Cloud组件的高可用性 (HA) 方法:

  • 区域永久性磁盘使用区域永久性磁盘时,数据会在一个区域中的两个可用区之间同步复制,因此您无需使用流式复制。但是,HA 仅限于一个区域内的两个可用区。
  • 有状态托管实例组。一对有状态 MIG 用作控制平面的一部分,让一个主 PostgreSQL 节点保持运行。当有状态 MIG 启动新实例时,它可以挂接现有的区域永久性磁盘。在单个时间点,两个 MIG 中只有一个具有正在运行的实例。
  • Cloud Storage。 Cloud Storage 存储桶中的对象包含一个配置,用于指示两个 MIG 中哪个 MIG 正在运行主数据库节点,以及在哪个 MIG 中创建故障切换实例。
  • MIG 健康检查和自动修复。健康检查会监控实例健康状况。如果正在运行的节点的健康状况变得不佳,则健康检查会启动自动修复过程。
  • 日志记录。当自动修复停止主节点时,Logging 中会记录一个条目。使用过滤条件将相关日志条目导出到 Pub/Sub 接收器主题。
  • 事件驱动型 Cloud Run functions。Pub/Sub 消息会触发 Cloud Run functions。Cloud Run functions 使用 Cloud Storage 中的配置来确定针对每个有状态 MIG 执行的操作。
  • 内部直通式网络负载均衡器。负载均衡器提供通往组中正在运行的实例的路由。这可确保从客户端中提取因重新创建实例引起的实例 IP 地址更改。

下图展示了使用有状态 MIG 和区域永久性磁盘的高可用性示例:

高可用性使用有状态 MIG 和区域永久性磁盘。

图 8.使用有状态 MIG 和区域永久性磁盘的高可用性图。

图 8 显示运行状况良好的主节点,用于处理客户端流量。客户端连接到内部直通网络负载均衡器的静态 IP 地址。负载均衡器将客户端请求路由到作为 MIG 的一部分运行的虚拟机。数据卷存储在装载的区域级永久性磁盘上。

如需实现此方法,请使用 PostgreSQL 创建一个虚拟机映像,该映像启动后用作 MIG 的实例模板。您还需要在节点上配置基于 HTTP 的健康检查(例如 HAProxy 或 pgDoctor)。基于 HTTP 的健康检查有助于确保负载均衡器和实例组都能确定 PostgreSQL 节点的健康状况。

区域永久性磁盘

如需预配在一个区域的两个可用区之间提供同步数据复制的块存储设备,您可以使用 Compute Engine 区域级永久性磁盘存储选项。区域永久性磁盘可以提供基础构建块,供您实现不依赖于 PostgreSQL 的内置流式复制的 PostgreSQL 高可用性选项。

如果您的主节点虚拟机实例因基础架构故障或可用区服务中断而不可用,则您可以强制将区域永久性磁盘挂接到同一区域的备份可用区中的虚拟机实例。

如需将区域永久性磁盘挂接到备份可用区的虚拟机实例,您可以执行以下操作之一:

  • 在备份区域中维护冷备用虚拟机实例。冷备用虚拟机实例是已停止的虚拟机实例,这些实例装载了区域永久性磁盘,但与主节点虚拟机实例相同。如果发生故障,则会启动冷备用虚拟机,并将区域永久性磁盘装载到该虚拟机。冷备用实例和主节点实例数据相同。
  • 使用相同的实例模板创建一对有状态 MIG。MIG 提供健康检查并用作控制平面的一部分。如果主节点发生故障,则系统会以声明方式在目标 MIG 中创建一个故障切换实例。目标 MIG 是在 Cloud Storage 对象中定义的。每个实例配置用于挂接区域永久性磁盘。

如果及时发现数据服务中断,强制挂接操作通常会在不到一分钟的时间内完成,因此可以使用分钟数来测量 RTO。

如果您的业务可以承受因需要检测和传达服务中断情况以及手动执行故障切换而产生的额外停机时间,则您无需自动执行强制挂接过程。如果 RTO 容忍度较低,则您可以自动执行检测和故障切换过程。或者,Cloud SQL for PostgreSQL 还提供了此高可用性方法的全托管式实现。

故障检测和故障切换过程

高可用性方法使用实例组的自动修复功能,通过健康检查来监控节点健康状况。如果存在健康检查失败,则现有实例会被视为健康状况不佳,并且会停止实例。此停止使用 Logging、Pub/Sub 和触发的 Cloud Run functions 函数启动故障切换过程。

为满足此虚拟机要求始终装载区域磁盘的要求,Cloud Run functions 会将两个 MIG 中的一个配置为在区域永久性磁盘可用的两个可用区之一中创建实例。节点发生故障后,系统会根据 Cloud Storage 中保留在备用可用区的状态启动替换实例。

在发生可用区故障期间,系统会启动替换实例。

图 9: MIG 中的可用区故障示意图。

在图 9 中,可用区 A 中的先前主节点已发生故障,Cloud Run functions 已将 MIG B 配置为在可用区 B 中启动新的主实例。故障检测机制会自动配置为监控新的主节点的运行状况。

查询路由

内部直通式网络负载均衡器将客户端路由到运行 PostgreSQL 服务的实例。负载均衡器使用与实例组相同的健康检查来确定实例是否可用于处理查询。如果节点由于正在重新创建而不可用,则连接将失败。实例备份后,健康检查会开始传递,并将新连接路由到可用节点。这种设置中没有任何只读节点,因为只有一个正在运行的节点。

回退过程

如果数据库节点因底层硬件问题导致健康检查失败,则系统会在其他底层实例上重新创建节点。此时,架构会恢复到其原始状态,您无需执行任何额外的步骤。但是,如果发生可用区故障,则设置会继续在降级状态下运行,直到第一个可用区恢复。虽然在极少数情况下,如果为区域永久性磁盘复制和有状态 MIG 配置的两个可用区同时发生故障,则 PostgreSQL 实例无法恢复 - 数据库在服务中断期间无法处理请求。

HA 选项对比

下表比较了 Patroni、pg_auto_failover 和具有区域永久性磁盘的有状态 MIG 的 HA 选项。

设置和架构

Patroni pg_auto_failover 具有区域永久性磁盘的有状态 MIG

需要 HA 架构、DCS 设置以及监控和提醒。数据节点上的代理设置相对简单。

不需要 PostgreSQL 以外的任何外部依赖项。需要一个用作监视器的节点。监控节点需要高可用性和灾难恢复,以确保其不是单点故障 (SPOF)。 仅包含 Google Cloud服务的架构。一次只能运行一个活动数据库节点。

高可用性的可配置性

Patroni pg_auto_failover 具有区域永久性磁盘的有状态 MIG
极其可配置:支持同步和异步复制,并且可让您指定哪些节点是同步和异步的节点。包括自动管理同步节点。允许设置多个地区和多区域高可用性设置。DCS 必须可访问。 与 Patroni 类似:极具可配置性。但是,由于 Monitor 仅可用于单个实例,因此任何类型的设置需要考虑该节点的访问权限。 仅限于具有同步复制功能的单个区域中的两个可用区。

处理网络分区的能力

Patroni pg_auto_failover 具有区域永久性磁盘的有状态 MIG
自我屏蔽和操作系统级监控功能有助于防范脑裂。如果连接到 DCS 失败,则主节点会将自身降级为副本并触发故障切换,以确保耐用性的优先级高于可用性。 结合使用从主节点到 Monitor 的健康检查以及从主节点到副本的健康检查,以检测网络分区,并在必要时将自身降级。 不适用:一次只能有一个有效的 PostgreSQL 节点,因此没有网络分区。

费用

Patroni pg_auto_failover 具有区域永久性磁盘的有状态 MIG
费用较高,因为这取决于您选择的 DCS 和 PostgreSQL 副本数量。Patroni 架构不会显著增加费用。不过,总体支出会受到底层基础设施的影响,该基础设施会将多个计算实例用于 PostgreSQL 和 DCS。由于此选项使用多个副本和单独的 DCS 集群,因此费用可能最高。 费用中等,因为这需要运行一个监控节点和至少三个 PostgreSQL 节点(一个主节点和两个副本)。 费用较低,因为在任何给定时间都只有一个 PostgreSQL 节点正在运行。您只需为单个计算实例付费。

客户端配置

Patroni pg_auto_failover 具有区域永久性磁盘的有状态 MIG
对客户端而言是透明的,因为它连接到负载均衡器。 要求客户端库在设置中支持多个主机定义,因为它不易前置负载均衡器。 对客户端而言是透明的,因为它连接到负载均衡器。

可伸缩性

Patroni pg_auto_failover 具有区域永久性磁盘的有状态 MIG
在配置可伸缩性和可用性权衡方面具有很高的灵活性。您可以通过添加更多副本来实现读取伸缩。 与 Patroni 类似:可以通过添加更多副本来实现读取伸缩。 由于一次只能有一个活跃的 PostgreSQL 节点,因此可伸缩性受限。

PostgreSQL 节点初始化和配置管理自动化

Patroni pg_auto_failover 具有区域永久性磁盘的有状态 MIG
提供管理 PostgreSQL 配置 (patronictl edit-config) 的工具,并自动初始化集群中的新节点或重启的节点。您可以使用 pg_basebackup 或其他工具(如 barman)初始化节点。 自动初始化节点,但仅限于初始化新副本节点时仅使用 pg_basebackup。配置管理仅限于 pg_auto_failover 相关配置。 具有共享磁盘的有状态实例组无需执行任何 PostgreSQL 节点初始化操作。由于只有一个节点在运行,因此配置管理仅在单个节点上进行。

可自定义性和功能丰富性

Patroni pg_auto_failover 具有区域永久性磁盘的有状态 MIG

提供钩子接口,以便在关键步骤(例如在降级或提升时)调用用户可定义的操作。

功能丰富的可配置性,例如支持不同类型的 DCS、初始化副本的不同方式,以及提供 PostgreSQL 配置的不同方法。

可让您设置允许级联副本集群的备用集群,以便轻松在集群之间迁移。

由于这是一个相对较新的项目,因此存在一些限制。 不适用。

成熟度

Patroni pg_auto_failover 具有区域永久性磁盘的有状态 MIG
项目自 2015 年推出,目前 Zalando 和 GitLab 等大型公司用于生产环境。 2019 年初公布的相对较新的项目。 完全由正式版 Google Cloud 产品组成。

维护和监控的最佳实践

维护和监控 PostgreSQL 高可用性集群对于确保高可用性、数据完整性和最佳性能至关重要。以下部分提供了一些有关监控和维护 PostgreSQL 高可用性集群的最佳实践。

定期执行备份和恢复测试

定期备份 PostgreSQL 数据库并测试恢复流程。 这样做有助于确保数据完整性,并在发生服务中断时最大限度地减少停机时间。测试恢复流程以验证备份,并发现潜在问题,避免发生服务中断。

监控 PostgreSQL 服务器和复制延迟

监控 PostgreSQL 服务器,验证它们是否正在运行。监控主节点和副本节点之间的复制延迟。延迟过长可能会导致数据不一致,并在发生故障切换时增加数据丢失。针对延迟时间显著增加的情况设置提醒,并及时调查根本原因。使用 pg_stat_replication 和 pg_replication_slots 等视图有助于您监控复制延迟。

实现连接池

连接池可以帮助您高效管理数据库连接。 连接池有助于减少建立新连接的开销,从而提高应用性能和数据库服务器稳定性。PGBouncer 和 Pgpool-II 等工具可以为 PostgreSQL 提供连接池。

实施全面的监控

如需深入了解 PostgreSQL 高可用性集群,请按如下所述建立强大的监控系统:

  • 监控关键 PostgreSQL 和系统指标,例如 CPU 利用率、内存用量、磁盘 I/O、网络活动和活跃连接。
  • 收集 PostgreSQL 日志(包括服务器日志、WAL 日志和自动完全清理日志),以便进行深入分析和问题排查。
  • 使用监控工具和信息中心直观呈现指标和日志,以便快速识别问题。
  • 将指标和日志与提醒系统集成,以便主动通知潜在问题。

如需详细了解如何监控 Compute Engine 实例,请参阅 Cloud Monitoring 概览。

后续步骤

贡献者

作者:Alex Cârciu | 解决方案架构师