理解和执行 PostgreSQL 故障转移与切换场景
在现代数据库架构中,通过高可用性 (HA) 确保持续运行至关重要。PostgreSQL 作为一款强大的开源关系型数据库,依赖流复制来维护跨多个节点的数据一致性。然而,当主服务器遇到问题或需要维护时,数据库管理员必须执行精确的步骤来恢复服务。本文将清晰地区分两种关键的 HA 操作——故障转移 (Failover) 和切换 (Switchover)——并详细介绍安全地将备用副本提升为新主库的步骤和注意事项。
理解这些事件之间的区别至关重要。切换是一种有计划的、受控的转换,而故障转移是对意外中断的紧急响应。成功应对这两种场景,都高度依赖于正确的配置、强大的监控以及对用于管理复制的工具的熟悉程度。
复制基础:HA 的基石
PostgreSQL 高可用性建立在流复制之上,其中一台服务器充当主库 (Primary)(或 Master),一台或多台服务器充当备库 (Standbys)(或 Replicas)。主库将预写日志 (WAL) 记录流式传输给备库,以使它们保持同步。
为了有效地管理这些角色,主节点和备用节点都需要特定的配置设置:
关键配置设置
这些设置控制着复制的操作方式以及节点如何相互识别:
wal_level:在主库上必须设置为replica或更高(如果使用需要逻辑解码的工具,理想情况下设置为logical)。max_wal_senders:定义了来自备库的最大并发连接数。必须从默认值(通常为 10)增加,以容纳所有备库。hot_standby:在备用服务器的postgresql.conf中必须设置为on,以允许在复制期间进行只读查询。synchronous_commit:控制事务确认。为了在切换期间实现零数据丢失,这通常设置为on(或为了轻微的延迟容忍度设置为remote_write)。primary_conninfo:在备库上设置,详细说明了连接到当前主库的连接信息(主机、端口、用户、密码)。
最佳实践: 为了实现强大的 HA,请使用连接池层(如 PgBouncer 或专用的 HA 代理,如 Patroni 或 Repmgr),它们可以抽象物理服务器地址,从而使应用程序的故障转移和切换过程无缝衔接。
切换 (Switchover):有计划的转换
切换是一个受控的、优雅的过程,其中主动的主节点被有意地停用,并提升指定的备库来取代其位置。此过程通常用于计划内的维护、版本升级或硬件更换。
受控切换的步骤
切换的目标是通过等待所有进行中的事务在提升前完成复制,从而确保零数据丢失。
- 停止当前主库上的写入: 第一步是阻止任何新的事务在当前主库上提交。这通常通过设置
default_transaction_read_only = on或暂时关闭客户端连接来实现。 - 等待复制追赶: 确保指定的备库已接收并应用了来自主库的所有剩余 WAL 记录。您可以通过主库上的
pg_stat_replication或检查备库的恢复状态来检查复制延迟。 - 启动备库提升: 执行命令将选定的备用服务器提升为主库角色。具体命令取决于所使用的管理工具(例如,
pg_ctl promote或集群管理器命令)。 - 重新配置旧主库: 一旦备库成功提升,旧主库必须被重新配置,作为备库追随新主库。这涉及更新其
primary_conninfo。 - 重定向应用程序: 更新负载均衡器或连接池器,将流量导向新的主服务器。
故障转移 (Failover):紧急响应
故障转移是一种即时的、反应性的程序,当当前主服务器意外故障(例如,硬件崩溃、网络分区、软件错误)且无法快速恢复在线时触发。
故障转移本身具有更高的数据丢失风险,因为不能保证在故障发生前,最后提交的几个事务有时间流式传输到备库。
执行紧急故障转移
故障转移程序旨在实现速度和恢复,通常利用专业工具来自动化提升过程。
- 确定旧主库的健康状况: 验证原始主库是否确实不可用,而不仅仅是经历了短暂的网络问题(这可以防止危险的“脑裂”场景)。
- 选择最佳备库: 选择复制延迟最小的备库(即 WAL 流中最靠前的那个)。
- 提升备库: 立即使用提升命令 (
pg_ctl promote) 提升选定的备库。 - 处理数据丢失(如有必要): 如果集群使用异步复制,则丢失在失败主库上的数据可能需要手动协调或直接接受,具体取决于应用程序的容忍度。
- 重新配置原有主库: 一旦原始主库恢复,必须对其进行清理、重新初始化(通常需要从新主库进行基础备份),并配置为追随新主库。
安全提升的工具:Repmgr 与 Patroni
虽然可以使用 pg_ctl 进行手动提升,但强大的 HA 环境依赖于专用工具来管理故障转移和切换所需的复杂协调工作,自动处理配置更改和集群状态管理。
Repmgr (复制管理器)
repmgr 是一款强大、轻量级的工具,用于监控复制并促进手动或自动故障转移。关键命令包括:
- 切换:
repmgr standby promote,后跟repmgr switchover --sibling-nodes-wait(确保追赶)。 - 故障转移:
repmgr failover
Patroni
Patroni 利用分布式共识存储(如 etcd、ZooKeeper 或 Consul)来管理集群状态,在检测到故障时自动选举新的主库。Patroni 通过 API 调用或 Kubernetes 操作符在很大程度上自动化了切换和故障转移,极大地减少了手动干预。
使用 Patroni 的示例(概念性提升命令):
# Triggering a switchover via Patroni's REST API
curl -X POST http://patroni-api-endpoint/switchover -H "Content-Type: application/json" -d '{"target": "standby_node_name"}'
关于脑裂的警告: 自动化故障转移期间最大的危险是“脑裂”场景,即由于网络分区,两个节点错误地认为自己是主库。Patroni 等工具使用仲裁机制来缓解这种情况,而手动设置则需要严格的隔离机制(如电源控制)来确保只存在一个主库。
差异总结
| 特性 | 切换 (Switchover)(计划性) | 故障转移 (Failover)(紧急性) |
|---|---|---|
| 触发因素 | 维护、升级、管理选择 | 主库故障(崩溃、中断) |
| 数据丢失风险 | 接近零(如果时机把握得当) | 中等到高(取决于复制模式) |
| 停机时间预期 | 短暂、受控的停机时间 | 立即的、反应性的停机时间 |
| 准备工作 | 需要事先协调和 WAL 同步确认 | 需要立即行动并依赖备库的健康状态 |
执行 PostgreSQL 故障转移和切换需要对集群状态和管理工具进行深入理解。虽然切换旨在通过协调实现零数据丢失,但故障转移优先考虑快速恢复服务,通常以牺牲最新的事务为代价。正确设置复制参数和利用强大的集群管理工具是可靠的 PostgreSQL 高可用性的基石。