前言
實現 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) + 嚴格監控。根據環境(自建/云)和需求選擇具體組件,并通過充分測試確保方案可靠性