首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

基於 PgPool 的 1主2從 PostgreSQL 流複製 HA 叢集完整部署實戰

     編輯:Java 綜合教學

架構設計目標

  • 強資料一致性 HA:同步流複製確保零資料遺失
  • 自動故障切換:PgPool 監控 + Watchdog 仲裁
  • 無縫切換:VIP 漂移 + 連線池透明切換

環境規劃

角色主機名IPPostgreSQLPgPool
Node 1node1192.168.0.211PrimaryStandby
Node 2node2192.168.0.212StandbyMaster (VIP)
Node 3node3192.168.0.213StandbyStandby
VIP-192.168.0.220-浮動

前置條件

  1. 三節點 SSH 互信 (免密登入)
  2. /etc/hosts 解析:192.168.0.211 pgsql_primary (Slave 復制連線用固定主機名)
  3. PostgreSQL 9.5 已配置 1主2從同步流複製 (synchronous_standby_names = 'node2,node3')
  4. Slave recovery.conf 設定 primary_conninfo = 'host=pgsql_primary ...'

PgPool 安裝 (三節點同步執行)

yum install https://www.pgpool.net/yum/rpms/3.5/redhat/rhel-7-x86_64/pgpool-II-release-3.5-1.noarch.rpm
yum install pgpool-II-pg95 pgpool-II-pg95-extensions

核心配置 pgpool.conf (以 Node 3 為例)

後端節點定義

backend_hostname0 = 'node1'
backend_port0 = 5433
backend_weight0 = 1
backend_data_directory0 = '/data/postgresql/data'
backend_flag0 = 'ALLOW_TO_FAILOVER'

backend_hostname1 = 'node2'
backend_port1 = 5433
backend_weight1 = 1
backend_data_directory1 = '/data/postgresql/data'
backend_flag1 = 'ALLOW_TO_FAILOVER'

backend_hostname2 = 'node3'
backend_port2 = 5433
backend_weight2 = 1
backend_data_directory2 = '/data/postgresql/data'
backend_flag2 = 'ALLOW_TO_FAILOVER'

主從模式與負載平衡

master_slave_mode = on
master_slave_sub_mode = 'stream'
load_balance_mode = on
sr_check_period = 10
sr_check_user = 'admin'
sr_check_password = 'admin'
sr_check_database = 'postgres'
delay_threshold = 10000000

健康檢查

health_check_period = 3
health_check_timeout = 20
health_check_user = 'admin'
health_check_password = 'admin'
health_check_database = 'postgres'
health_check_max_retries = 0
health_check_retry_delay = 1
connect_timeout = 10000
failover_command = '/home/postgres/failover.sh %h %H %d %P'
fail_over_on_backend_error = on
search_primary_node_timeout = 10

Watchdog 高可用 (三節點奇數仲裁)

use_watchdog = on
wd_hostname = 'node3'
wd_port = 9000
wd_priority = 1
wd_authkey = ''
wd_ipc_socket_dir = '/tmp'
delegate_IP = '192.168.0.220'  # VIP
if_cmd_path = '/usr/sbin'
if_up_cmd = 'ip addr add $_IP_$/24 dev eno16777736 label eno16777736:0'
if_down_cmd = 'ip addr del $_IP_$/24 dev eno16777736'
arping_path = '/usr/sbin'
arping_cmd = 'arping -U $_IP_$ -w 1 -I eno16777736'
wd_lifecheck_method = 'heartbeat'
wd_interval = 10
wd_heartbeat_port = 9694
wd_heartbeat_keepalive = 2
wd_heartbeat_deadtime = 30

# 心跳目標節點
heartbeat_destination0 = 'node1'
heartbeat_destination_port0 = 9694
heartbeat_device0 = 'eno16777736'
heartbeat_destination1 = 'node2'
heartbeat_destination_port1 = 9694
heartbeat_device1 = 'eno16777736'

# 其他 PgPool 節點
other_pgpool_hostname0 = 'node1'
other_pgpool_port0 = 9999
other_wd_port0 = 9000
other_pgpool_hostname1 = 'node2'
other_pgpool_port1 = 9999
other_wd_port1 = 9000

PCP 管理介面配置

# 產生密碼雜湊
pg_md5 pgpool
# ba777e4c2f15c11ea8ac3be7e0440aa0

# pcp.conf
root:ba777e4c2f15c11ea8ac3be7e0440aa0

# 免密檔案 ~/.pcppass (chmod 600)
localhost:9898:root:pgpool

Failover 腳本部署 (/home/postgres/failover.sh)

核心邏輯:

  1. 若故障為 Standby → 直接返回
  2. 確認 Old Master 真掛掉 (避免腦裂誤判)
  3. 驗證其他 Standby 狀態正常
  4. 比較 XLOG 位置,選最新節點為新 Primary
  5. SSH 到各 Standby 執行 change_replication_source.sh 修改 /etc/hosts 切換 pgsql_primary 解析
  6. 觸發新 Primary pg_ctl promote

change_replication_source.sh

#!/bin/bash
new_primary=$1
cat /etc/hosts | grep -v ' pgsql_primary$' > /tmp/hosts.tmp
echo "`resolveip -s $new_primary` pgsql_primary" >> /tmp/hosts.tmp
cp -f /tmp/hosts.tmp /etc/hosts

啟動與驗證

# 三節點啟動
service pgpool start

# 檢查 Watchdog 狀態
pcp_watchdog_info -w -v
# 確認 Quorum EXIST、VIP 掛載節點、Master/Standby 狀態

# 檢查後端狀態
psql -h node3 -p 9999 -U admin postgres -c "show pool_nodes;"
# 確認 role: primary/standby、status: 2 (up)

故障切換測試

  1. 初始狀態:Node1 Primary、Node2/3 Standby、VIP 在 Node2
  2. 殺死 Node1 PostgreSQL:killall -9 postgres
  3. 觀察:PgPool 偵測故障 → 執行 failover.sh → Node2 升為 Primary → VIP 漂移
  4. Client 連線 VIP 192.168.0.220:9999 無感切換

故障節點恢復 (Node1 重新加入)

# 1. 更新 /etc/hosts 指向新 Primary
vi /etc/hosts
192.168.0.212 pgsql_primary

# 2. 從新 Primary 拉取基礎備份
su - postgres
cp /data/postgresql/data/recovery.done /tmp/
rm -rf /data/postgresql/data
pg_basebackup -h pgsql_primary -p 5433 -U replication -D /data/postgresql/data -X stream -P
cp /tmp/recovery.done /data/postgresql/data/recovery.conf

# 3. 啟動 PostgreSQL
pg_ctl -D /data/postgresql/data start

# 4. 掛載回 PgPool
pcp_attach_node -w 0

# 5. 驗證
show pool_nodes; # Node1 status=1 (starting) → 2 (up)、role=standby

已知問題與避坑

  1. PgPool 與 PostgreSQL 同機部署風險:PgPool Master 斷網導致整叢集阻塞 (Bug),建議**分離部署**
  2. Address already in use:rm -f /tmp/.s.PGSQL.9999
  3. Slave 追新 Primary 需自行實現腳本,官方無內建

總結

本架構透過 PgPool Watchdog 實現 VIP 浮動與自動 Failover,配合 /etc/hosts 切換復制源實現 Slave 追新 Primary。生產環境強烈建議:**PgPool 獨立部署於應用層**,避免與資料庫爭搶資源並規避單點故障擴散。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved