如何實現PostgreSQL的高可用性,包括主流的復制方案、負載均衡方法以及故障轉移流程?

前言

實現 PostgreSQL 的高可用性(High Availability, HA)是一個系統工程,需要結合復制技術、連接路由(負載均衡)、自動故障轉移(Failover)以及監控告警。以下是主流方案和關鍵流程的詳細說明:


一、核心基礎:復制(Replication)

所有 HA 方案都建立在可靠的數據復制之上。

  1. 物理流復制(Physical Streaming Replication, PSR)

    • 原理:主庫(Primary)持續將 WAL(Write-Ahead Log)記錄流式傳輸給一個或多個備庫(Standby)。備庫實時重放 WAL,保持與主庫物理數據塊級別一致。
    • 模式
      • 異步復制(Async):主庫提交事務后無需等待備庫確認。性能最好,但存在數據丟失風險(主庫宕機時未傳輸的 WAL)。
      • 同步復制(Sync):主庫提交事務必須等待至少一個指定備庫接收并寫入 WAL 后才返回成功。保證零數據丟失,但增加延遲且依賴備庫可用性。通常配置為 synchronous_standby_names = 'ANY 1 (standby1, standby2)' 以平衡可靠性和性能。
    • 優點:簡單、高效、低開銷、數據一致性高(物理一致)。
    • 缺點:備庫通常只讀,不能寫入;大版本升級需重建備庫。
  2. 邏輯復制(Logical Replication)

    • 原理:基于發布/訂閱模型。主庫將預定義的邏輯變更(INSERT/UPDATE/DELETE)解碼后發送給訂閱者(備庫)。備庫獨立應用這些變更。
    • 優點:支持跨大版本復制、可選擇復制特定表/行/列、備庫可讀寫。
    • 缺點:開銷大于 PSR、延遲通常更高、序列/DDL 變更需額外處理、不保證完全物理一致。
    • 適用場景:多主架構(需應用層解決沖突)、數據分片聚合、跨版本升級、部分表同步。

二、故障轉移(Failover)與自動切換

核心目標是主庫故障時,快速將流量切換到最新備庫并提升為新主庫。

  1. 關鍵組件:

    • 高可用管理器(HA Manager):負責監控、決策和執行故障轉移。主流選擇:
      • Patroni(推薦):結合 DCS(如 etcd, Consul, ZooKeeper)存儲集群狀態,提供自動故障轉移、主庫選舉、配置管理。支持自定義腳本。
      • repmgr:輕量級工具,提供監控、故障轉移通知和手動/自動切換命令。
      • Pgpool-II:內置 HA 管理功能(需謹慎配置避免腦裂)。
      • 云托管服務(RDS, Cloud SQL, Azure DB):使用其內置的 HA 方案。
    • 分布式一致性存儲(DCS):如 etcd/Consul/ZooKeeper。存儲集群拓撲、主庫標識、健康狀態、配置。防止腦裂(Split-Brain)的核心。
  2. 故障轉移流程(以 Patroni + etcd 為例):

    1. 監控與檢測:Patroni Agent 在每個節點運行,定期檢查本地 PostgreSQL 狀態(進程、連接性、WAL 進度、復制延遲)。
    2. 故障判定:當主庫的 Agent 無法續租 DCS 中的 Leader 租約(TTL過期),或備庫 Agent 檢測到主庫連接失敗 + 復制中斷超過閾值。
    3. Leader 選舉
    • 存活的備庫節點在 DCS 中發起選舉。
    • 基于預設規則(如 prioritylag)選擇最合適的備庫。
    • DCS 確保只有一個節點能贏得選舉。
    1. 新主庫提升(Promotion)
    • 當選節點執行 pg_ctl promoteSELECT pg_promote(),脫離恢復模式,成為可讀寫主庫。
    • 更新 DCS 中的 Leader 記錄。
    1. 舊主庫隔離(Fencing):若舊主庫可能存活,需確保其不能繼續寫入(避免腦裂)。方法:
    • Patroni 調用腳本(如 pg_ctl stop -m fast, kill -9, iptables 阻斷端口,或通過管理接口關機)。
    • 硬件/云層面的隔離(STONITH)。
    1. 重新配置復制:剩余備庫自動根據 DCS 中的新主庫信息,使用 pg_rewind(若舊主庫可連接且時間線未偏離太多)或重建方式(pg_basebackup)重新指向新主庫復制。

三、負載均衡與連接路由

確保應用連接始終指向可用主庫或分發到只讀備庫。

  1. 讀寫分離(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):配合健康檢查使用。
  2. 主庫連接路由

    • 虛擬 IP(VIP):主庫綁定一個 VIP。故障轉移時,新主庫接管該 VIP(通過 arping, VRRP/Keepalived 或云供應商的浮動 IP)。
    • DNS 更新:故障轉移后更新 DNS 記錄指向新主庫 IP(TTL 需足夠短)。響應慢,通常作為備用方案。
    • 服務發現:應用通過查詢 DCS(如 Consul DNS Interface)或 Patroni REST API (GET /primary) 動態獲取當前主庫地址。現代云原生應用常用方式。

四、推薦高可用架構方案

  1. 經典方案:Patroni + PSR + HAProxy/Keepalived

    • 節點:1 主 + N 同步/異步備庫(至少 2 個節點)。
    • HA 管理:Patroni + etcd/Consul(3節點避免腦裂)。
    • 連接路由:
      • 寫請求:應用連接 VIP(由 Keepalived 管理)或通過 HAProxy(配置主庫健康檢查)。
      • 讀請求:HAProxy 負載均衡到所有健康備庫。
    • 優點:成熟、靈活、社區支持好。
  2. 云原生方案:Patroni + PSR + Kubernetes Service

    • 在 K8s 上部署 PostgreSQL StatefulSet。
    • Patroni 使用 K8s API 作為 DCS(替代 etcd)。
    • 讀寫服務:K8s Service ClusterIPLoadBalancer,后端指向 Patroni 管理的 Leader Pod。
    • 只讀服務:指向非 Leader Pods。
    • 優點:無縫集成 K8s 生態(監控、日志、滾動更新)。
  3. 托管數據庫服務(RDS/Aurora, Cloud SQL, Azure DB)

    • 使用云服務商提供的 HA 方案(通常基于 PSR 或共享存儲)。
    • 自動處理復制、備份、故障轉移、維護窗口。
    • 優點:省運維,開箱即用。缺點:成本較高,靈活性受限。

五、關鍵注意事項

  1. 監控告警

    • 核心指標:節點狀態、主備延遲(pg_stat_replication)、連接數、鎖、WAL 積壓、存儲空間、HA 管理器狀態。
    • 工具:Prometheus + Grafana(配合 postgres_exporter)、Zabbix、云監控。
  2. 定期備份:HA ≠ 備份!必須保留獨立于主集群的 PITR 備份(如 pg_basebackup + WAL 歸檔到 S3/MinIO)。

  3. 測試!測試!測試!

    • 定期模擬主庫宕機(kill -9 postgres, 關機),驗證故障轉移時間(RTO)和數據丟失量(RPO)。
    • 測試網絡分區場景,確保腦裂防護生效。
  4. 腦裂防護(Split-Brain Prevention)

    • 嚴格依賴 DCS 的分布式鎖和租約機制。
    • 配置足夠的備庫(建議至少 2 個)。
    • 使用隔離(Fencing)機制。
  5. 應用重連機制

  • 應用需處理連接中斷,實現自動重試和重連(使用支持自動重連的連接池)。

總結:

實現 PostgreSQL 高可用性的黃金標準是:物理流復制(PSR) + Patroni(管理故障轉移) + HAProxy/PGBouncer(連接池/路由) + 分布式存儲(etcd/Consul) + 嚴格監控。根據環境(自建/云)和需求選擇具體組件,并通過充分測試確保方案可靠性

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/92853.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/92853.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/92853.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Apache Ignite 生產級的線程池關閉工具方法揭秘

Apache Ignite 中用于 安全、可靠地關閉線程池&#xff08;ExecutorService&#xff09; 的關鍵邏輯。我們來一步步深入理解它的設計思想和實現細節。&#x1f9f1; 一、核心方法&#xff1a;U.shutdownNow(...) public static void shutdownNow(Class<?> owner, Nullab…

Unity:GUI筆記(一)——文本、按鈕、多選框和單選框、輸入框和拖動條、圖片繪制和框繪制

寫在前面&#xff1a;寫本系列(自用)的目的是回顧已經學過的知識、記錄新學習的知識或是記錄心得理解&#xff0c;方便自己以后快速復習&#xff0c;減少遺忘。主要是唐老師的課程。一、重要參數、文本、按鈕GUI相關代碼需要寫在private void OnGUI()中。該函數每幀執行&#x…

wordpress從wp_nav_menu中獲取菜單項

從wp_nav_menu中獲取菜單項&#xff0c;然后檢查這些菜單項是否對應分類(Category)&#xff0c;并輸出這些分類的ID。 以下是完整的代碼實現&#xff1a; <?php // 獲取指定菜單位置的菜單項 $menu_items wp_get_nav_menu_items(wodepress); // wodepress 是菜單位置的名…

第4章 程序段的反復執行2 while語句P128練習題(題及答案)

&#xff08;&#xff08;1&#xff09;閱讀程序#include <bits/stdc.h> using namespace std; //湯永紅 int main(){int n,s0;cin >> n;while(n){s s * 10 n % 10;n / 10;}cout << s << endl;return 0; }分別輸入&#xff1a;0 1024 1234567890輸出…

圖解軟件系統組成

這是基于 ??PlantUML?? 繪制的軟件系統組成部分思維導圖&#xff0c;聚焦技術路線與文件類型的對應關系&#xff0c;采用分層架構展示核心模塊&#xff1a;startmindmap * **軟件系統組成部分*** **一、核心技術棧*** 后端技術* 技術路線: Python Web 框架* 文件類型: .py …

【傳奇開心果系列】Flet框架實現的多人訪問web數據表高并發前后端自定義框架模板

Flet框架實現的多人訪問web數據表高并發前后端自定義框架模板一、效果展示截圖二、應用場景介紹1. **多用戶實時協作**2. **產品管理**3. **數據可視化**三、特色說明1. **實時通信**2. **高性能**3. **用戶友好的界面**4. **日志記錄**5. **安全性**四、總結五、源碼下載地址六…

農業智慧大屏系統 - Flask + Vue實現

下面我將實現一個完整的農業智慧大屏系統&#xff0c;使用Flask作為后端框架&#xff0c;前端使用Vue.js結合ECharts進行數據可視化展示。 設計思路 前端部分&#xff1a; 使用Vue.js構建響應式界面 使用ECharts實現各類農業數據可視化 使用CSS Grid布局實現大屏適配 后端…

Linux中Https配置與私有CA部署指南

Linux中Https配置與私有CA部署指南 一、HTTPS 核心概念特性HTTPHTTPS協議明文傳輸HTTP SSL/TLS端口80443加密未加密數據加密二、SSL/TLS 握手流程 Client → Server ClientHello&#xff1a;支持哪些版本、支持哪些加密算法&#xff0c;隨機生成一組32字節數據 random_c Serve…

【軟考架構】主流數據持久化技術框架

JDO與JPA JDO&#xff08;Java Data Objects&#xff09;和JPA&#xff08;Java Persistence API&#xff09;都是Java中用于對象持久化的規范&#xff0c;但它們在設計目標、技術背景和應用場景上存在顯著區別。以下是兩者的核心對比&#xff1a;1. 規范背景與維護方 JDO&…

服務日志、監控

服務怎么做監控和告警使用 Prometheus 和 Grafana 來實現整個微服務集群的監控和告警&#xff1a;Prometheus&#xff1a;Prometheus 是一個開源的監控系統&#xff0c;具有靈活的數據模型和強大的查詢語言&#xff0c;能夠收集和存儲時間序列數據。它可以通過 HTTP 協議定期拉…

秋招筆記-8.12

我決定從今天開始&#xff0c;在每天的學習內容中加入算法的內容&#xff0c;大致分布時間的話&#xff0c;假設我一天可以學習八個小時&#xff0c;那算法兩個小時&#xff0c;八股三個小時&#xff0c;項目三個小時這樣的分布差不多吧。之所以還是需要做做筆試一是為了應對面…

【從0帶做】基于Springboot3+Vue3的校園表白墻系統

大家好&#xff0c;我是武哥&#xff0c;最近給大家手擼了一個基于SpringBoot3Vue3的校園表白墻系統&#xff0c;可用于畢業設計、課程設計、練手學習&#xff0c;系統全部原創&#xff0c;如有遇到網上抄襲站長的&#xff0c;歡迎聯系博主~ 資料獲取方式 請點開作者頭像看下…

【Linux系列】服務器 IP 地址查詢

博客目錄一、hostname 命令&#xff1a;簡單高效的 IP 查詢工具命令詳解實際應用技巧注意事項二、ip 命令&#xff1a;新一代網絡配置全能工具基本用法在服務器管理和網絡運維中&#xff0c;快速準確地獲取服務器的 IP 地址是一項基本但至關重要的技能。無論是進行遠程連接、配…

【完美解決】在 Ubuntu 24.04 上為小米 CyberDog 2 刷機/交叉編譯:終極 Docker 環境搭建指南

摘要 本文旨在為廣大開發者提供一份在非官方推薦的 Ubuntu 24.04 系統上&#xff0c;成功為小米機器狗 CyberDog 2 進行刷機和交叉編譯的終極解決方案。通過層層排查 setup.sh 依賴缺失、No devices to flash 以及交叉編譯 Segmentation fault 等疑難雜癥&#xff0c;我們發現根…

XX生產線MES系統具體實施方案

一、系統架構設計1. 整體架構圖2. 技術組件清單模塊技術選型部署要求應用服務Spring Boot 3.2 Spring CloudKubernetes Pod (4C8G)實時通信Kafka 3.6 WebSocket3節點集群工業協議Eclipse Milo (OPC UA)獨立服務器 (2C4G)數據庫PostgreSQL 15 TimescaleDB 2.10SSD存儲, 主從復…

Go語言實戰案例:使用模板渲染HTML頁面

在 Web 開發中&#xff0c;身份驗證是一個繞不開的話題。傳統的 Session 機制依賴服務器存儲用戶狀態&#xff0c;而在微服務、分布式架構下&#xff0c;這種方式可能會導致狀態同步困難。 JWT&#xff08;JSON Web Token&#xff09;是一種無狀態的、跨平臺的身份驗證解決方案…

@RequestMapping接收文件格式的形參(方法參數)

需求&#xff1a;將文件上傳到OSS&#xff0c;忽略域名與路徑&#xff0c;將文件名以 “img1.png,img2.png,img3.png”保存到數據庫中 1、先看結果 后端要接收postman傳遞的file文件2、SpringBoot接收參數方式 很顯然&#xff0c;上面postman上傳的地方可以傳入多個文件&#x…

【數據分享】2020-2022年我國鄉鎮的逐日最高氣溫數據(Shp/Excel格式)

之前我們分享過2020—2022年中國0.01分辨率逐日最高氣溫柵格數據&#xff08;可以查看之前的文章獲悉詳情&#xff09;&#xff01;該數據是研究者張凌, 胡英屹等發布在國家冰川凍土沙漠科學數據中心平臺上的高分辨最高氣溫數據。很多小伙伴拿到數據后反饋柵格數據不太方便使用…

為什么C++主函數 main 要寫成 int 返回值 | main(int argc, char* argv[]) 這種寫法是什么意思?

主函數 main 要寫成 int 返回值&#xff1f;main(int argc, char* argv[]) 為什么里面沒有 cin 也能讀到數據&#xff0c;數據是怎么傳進去的&#xff1f;本文將一步步回答這些問題。1. 為什么 main 要寫成 intC 標準&#xff08;ISO/IEC 14882&#xff09;規定&#xff0c;mai…

【oracle閃回查詢】記錄字段短時間被修改的記錄

SELECT versions_starttime, versions_endtime, versions_operation, versions_xid, [字段1], [字段2] – 替換為實際字段名 FROM 表名 VERSIONS BETWEEN TIMESTAMP SYSTIMESTAMP - INTERVAL ‘15’ MINUTE AND SYSTIMESTAMP --15分鐘內 WHERE id ‘目標ID’ – 指定記錄的唯…