前言
实现 PostgreSQL 的高可用性(High Availability, HA)是一个系统工程,需要结合复制技术、连接路由(负载均衡)、自动故障转移(Failover)以及监控告警。以下是主流方案和关键流程的详细说明:
一、核心基础:复制(Replication)
所有 HA 方案都建立在可靠的数据复制之上。
物理流复制(Physical Streaming Replication, PSR)
- 原理:主库(Primary)持续将 WAL(Write-Ahead Log)记录流式传输给一个或多个备库(Standby)。备库实时重放 WAL,保持与主库物理数据块级别一致。
- 模式:
- 异步复制(Async):主库提交事务后无需等待备库确认。性能最好,但存在数据丢失风险(主库宕机时未传输的 WAL)。
- 同步复制(Sync):主库提交事务必须等待至少一个指定备库接收并写入 WAL 后才返回成功。保证零数据丢失,但增加延迟且依赖备库可用性。通常配置为
synchronous_standby_names = 'ANY 1 (standby1, standby2)'
以平衡可靠性和性能。
- 优点:简单、高效、低开销、数据一致性高(物理一致)。
- 缺点:备库通常只读,不能写入;大版本升级需重建备库。
逻辑复制(Logical Replication)
- 原理:基于发布/订阅模型。主库将预定义的逻辑变更(INSERT/UPDATE/DELETE)解码后发送给订阅者(备库)。备库独立应用这些变更。
- 优点:支持跨大版本复制、可选择复制特定表/行/列、备库可读写。
- 缺点:开销大于 PSR、延迟通常更高、序列/DDL 变更需额外处理、不保证完全物理一致。
- 适用场景:多主架构(需应用层解决冲突)、数据分片聚合、跨版本升级、部分表同步。
二、故障转移(Failover)与自动切换
核心目标是主库故障时,快速将流量切换到最新备库并提升为新主库。
关键组件:
- 高可用管理器(HA Manager):负责监控、决策和执行故障转移。主流选择:
- Patroni(推荐):结合 DCS(如 etcd, Consul, ZooKeeper)存储集群状态,提供自动故障转移、主库选举、配置管理。支持自定义脚本。
- repmgr:轻量级工具,提供监控、故障转移通知和手动/自动切换命令。
- Pgpool-II:内置 HA 管理功能(需谨慎配置避免脑裂)。
- 云托管服务(RDS, Cloud SQL, Azure DB):使用其内置的 HA 方案。
- 分布式一致性存储(DCS):如 etcd/Consul/ZooKeeper。存储集群拓扑、主库标识、健康状态、配置。防止脑裂(Split-Brain)的核心。
- 高可用管理器(HA Manager):负责监控、决策和执行故障转移。主流选择:
故障转移流程(以 Patroni + etcd 为例):
- 监控与检测:Patroni Agent 在每个节点运行,定期检查本地 PostgreSQL 状态(进程、连接性、WAL 进度、复制延迟)。
- 故障判定:当主库的 Agent 无法续租 DCS 中的 Leader 租约(TTL过期),或备库 Agent 检测到主库连接失败 + 复制中断超过阈值。
- Leader 选举:
- 存活的备库节点在 DCS 中发起选举。
- 基于预设规则(如
priority
、lag
)选择最合适的备库。 - DCS 确保只有一个节点能赢得选举。
- 新主库提升(Promotion):
- 当选节点执行
pg_ctl promote
或SELECT pg_promote()
,脱离恢复模式,成为可读写主库。 - 更新 DCS 中的 Leader 记录。
- 旧主库隔离(Fencing):若旧主库可能存活,需确保其不能继续写入(避免脑裂)。方法:
- Patroni 调用脚本(如
pg_ctl stop -m fast
,kill -9
,iptables
阻断端口,或通过管理接口关机)。 - 硬件/云层面的隔离(STONITH)。
- 重新配置复制:剩余备库自动根据 DCS 中的新主库信息,使用
pg_rewind
(若旧主库可连接且时间线未偏离太多)或重建方式(pg_basebackup
)重新指向新主库复制。
三、负载均衡与连接路由
确保应用连接始终指向可用主库或分发到只读备库。
读写分离(Read/Write Splitting)
- 应用层实现:应用代码根据 SQL 类型(读/写)选择连接主库或只读备库池。需框架支持(如 Java 的 ShardingSphere, Python 的 SQLAlchemy)。
- 中间件实现:
- Pgpool-II:位于应用和 PG 之间。解析 SQL,将写请求路由到主库,读请求路由到备库池。支持连接池、负载均衡算法(round-robin, least conn)。注意:启用负载均衡时需禁用其内建 HA 管理以避免冲突(推荐用 Patroni 管理 HA)。
- HAProxy:TCP 层代理。需结合外部机制(如 Patroni REST API)动态更新主库和备库列表的健康检查状态。
- 云负载均衡器(如 AWS ELB/NLB, GCP Load Balancer):配合健康检查使用。
主库连接路由
- 虚拟 IP(VIP):主库绑定一个 VIP。故障转移时,新主库接管该 VIP(通过
arping
, VRRP/Keepalived 或云供应商的浮动 IP)。 - DNS 更新:故障转移后更新 DNS 记录指向新主库 IP(TTL 需足够短)。响应慢,通常作为备用方案。
- 服务发现:应用通过查询 DCS(如 Consul DNS Interface)或 Patroni REST API (
GET /primary
) 动态获取当前主库地址。现代云原生应用常用方式。
- 虚拟 IP(VIP):主库绑定一个 VIP。故障转移时,新主库接管该 VIP(通过
四、推荐高可用架构方案
经典方案:Patroni + PSR + HAProxy/Keepalived
- 节点:1 主 + N 同步/异步备库(至少 2 个节点)。
- HA 管理:Patroni + etcd/Consul(3节点避免脑裂)。
- 连接路由:
- 写请求:应用连接 VIP(由 Keepalived 管理)或通过 HAProxy(配置主库健康检查)。
- 读请求:HAProxy 负载均衡到所有健康备库。
- 优点:成熟、灵活、社区支持好。
云原生方案:Patroni + PSR + Kubernetes Service
- 在 K8s 上部署 PostgreSQL StatefulSet。
- Patroni 使用 K8s API 作为 DCS(替代 etcd)。
- 读写服务:K8s Service
ClusterIP
或LoadBalancer
,后端指向 Patroni 管理的 Leader Pod。 - 只读服务:指向非 Leader Pods。
- 优点:无缝集成 K8s 生态(监控、日志、滚动更新)。
托管数据库服务(RDS/Aurora, Cloud SQL, Azure DB)
- 使用云服务商提供的 HA 方案(通常基于 PSR 或共享存储)。
- 自动处理复制、备份、故障转移、维护窗口。
- 优点:省运维,开箱即用。缺点:成本较高,灵活性受限。
五、关键注意事项
监控告警:
- 核心指标:节点状态、主备延迟(
pg_stat_replication
)、连接数、锁、WAL 积压、存储空间、HA 管理器状态。 - 工具:Prometheus + Grafana(配合
postgres_exporter
)、Zabbix、云监控。
- 核心指标:节点状态、主备延迟(
定期备份:HA ≠ 备份!必须保留独立于主集群的 PITR 备份(如
pg_basebackup
+ WAL 归档到 S3/MinIO)。测试!测试!测试!:
- 定期模拟主库宕机(
kill -9 postgres
, 关机),验证故障转移时间(RTO)和数据丢失量(RPO)。 - 测试网络分区场景,确保脑裂防护生效。
- 定期模拟主库宕机(
脑裂防护(Split-Brain Prevention):
- 严格依赖 DCS 的分布式锁和租约机制。
- 配置足够的备库(建议至少 2 个)。
- 使用隔离(Fencing)机制。
应用重连机制:
- 应用需处理连接中断,实现自动重试和重连(使用支持自动重连的连接池)。
总结:
实现 PostgreSQL 高可用性的黄金标准是:物理流复制(PSR) + Patroni(管理故障转移) + HAProxy/PGBouncer(连接池/路由) + 分布式存储(etcd/Consul) + 严格监控。根据环境(自建/云)和需求选择具体组件,并通过充分测试确保方案可靠性