Ubuntu 22.04 PostgreSQL Streaming Replication

Ubuntu 22.04 PostgreSQL Streaming Replication Setup

PostgreSQL Streaming Replication 是一種高可用性解決方案,可以將資料從主伺服器即時複製到一個或多個從伺服器。本文將詳細介紹如何在 Ubuntu 22.04 上設定 PostgreSQL Streaming Replication。

Streaming Replication 概述

Streaming Replication(串流複製)是 PostgreSQL 提供的原生複製功能,自 PostgreSQL 9.0 版本開始引入。它透過將 WAL(Write-Ahead Log)記錄從主伺服器串流傳輸到從伺服器來實現資料同步。

主要特點

  • 即時同步:資料變更幾乎可以即時複製到從伺服器
  • 讀取擴展:從伺服器可以處理唯讀查詢,分散讀取負載
  • 高可用性:當主伺服器發生故障時,可以將從伺服器提升為新的主伺服器
  • 多從伺服器支援:一個主伺服器可以同時複製到多個從伺服器
  • 級聯複製:從伺服器也可以作為其他從伺服器的來源

同步與非同步複製

PostgreSQL Streaming Replication 支援兩種複製模式:

非同步複製(Asynchronous)

  • 預設模式:主伺服器不等待從伺服器確認即提交事務
  • 效能較佳:不會因等待從伺服器而影響主伺服器效能
  • 資料延遲:可能存在短暫的資料延遲,故障時可能遺失少量資料

同步複製(Synchronous)

  • 資料一致性:主伺服器等待至少一個從伺服器確認後才提交事務
  • 零資料遺失:確保從伺服器與主伺服器資料完全同步
  • 效能影響:會增加事務提交的延遲

環境準備

本教學假設您有兩台 Ubuntu 22.04 伺服器:

角色主機名稱IP 位址
主伺服器(Primary)pg-primary192.168.1.10
從伺服器(Standby)pg-standby192.168.1.11

安裝 PostgreSQL

在兩台伺服器上都安裝 PostgreSQL:

1
2
sudo apt update
sudo apt install postgresql postgresql-contrib -y

確認安裝版本:

1
psql --version

主伺服器設定

1. 修改 postgresql.conf

編輯主伺服器的設定檔:

1
sudo nano /etc/postgresql/14/main/postgresql.conf

修改以下參數:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 監聽所有網路介面
listen_addresses = '*'

# WAL 設定
wal_level = replica
max_wal_senders = 10
wal_keep_size = 1GB

# 可選:啟用同步複製
# synchronous_commit = on
# synchronous_standby_names = 'pg-standby'

# 歸檔設定(建議啟用)
archive_mode = on
archive_command = 'cp %p /var/lib/postgresql/14/archive/%f'

參數說明:

  • wal_level:設為 replica 以支援串流複製
  • max_wal_senders:允許的最大 WAL sender 程序數量
  • wal_keep_size:保留的 WAL 檔案大小
  • archive_mode:啟用 WAL 歸檔

2. 建立歸檔目錄

1
2
sudo mkdir -p /var/lib/postgresql/14/archive
sudo chown postgres:postgres /var/lib/postgresql/14/archive

建立複製使用者

1. 建立專用複製帳號

在主伺服器上建立複製專用的使用者:

1
sudo -u postgres psql
1
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'your_secure_password';

2. 設定存取權限

編輯 pg_hba.conf 允許從伺服器連線:

1
sudo nano /etc/postgresql/14/main/pg_hba.conf

加入以下設定:

1
2
# 允許複製連線
host    replication     replicator      192.168.1.11/32         scram-sha-256

3. 重新啟動主伺服器

1
sudo systemctl restart postgresql

4. 驗證主伺服器設定

1
2
sudo -u postgres psql -c "SHOW wal_level;"
sudo -u postgres psql -c "SHOW max_wal_senders;"

從伺服器設定

1. 停止 PostgreSQL 服務

1
sudo systemctl stop postgresql

2. 清除現有資料目錄

1
sudo rm -rf /var/lib/postgresql/14/main/*

使用 pg_basebackup

1. 執行基礎備份

使用 pg_basebackup 從主伺服器複製資料:

1
sudo -u postgres pg_basebackup -h 192.168.1.10 -U replicator -D /var/lib/postgresql/14/main -Fp -Xs -P -R

參數說明:

  • -h:主伺服器 IP 位址
  • -U:複製使用者名稱
  • -D:目標資料目錄
  • -Fp:使用 plain 格式
  • -Xs:使用串流方式傳輸 WAL
  • -P:顯示進度
  • -R:自動建立 standby.signal 和設定複製連線

2. 驗證複製設定檔

pg_basebackup 會自動建立 standby.signal 檔案和更新 postgresql.auto.conf

1
2
cat /var/lib/postgresql/14/main/standby.signal
cat /var/lib/postgresql/14/main/postgresql.auto.conf

postgresql.auto.conf 應包含類似以下內容:

1
primary_conninfo = 'user=replicator password=your_secure_password host=192.168.1.10 port=5432 sslmode=prefer'

3. 設定從伺服器參數(可選)

編輯從伺服器的 postgresql.conf

1
sudo nano /etc/postgresql/14/main/postgresql.conf

可選設定:

1
2
3
4
5
# 允許從伺服器處理唯讀查詢
hot_standby = on

# 回饋主伺服器的複製進度
hot_standby_feedback = on

4. 啟動從伺服器

1
sudo systemctl start postgresql

驗證複製狀態

在主伺服器上檢查

查看 WAL sender 程序

1
sudo -u postgres psql -c "SELECT * FROM pg_stat_replication;"

重要欄位說明:

  • pid:WAL sender 程序 ID
  • usename:複製使用者名稱
  • client_addr:從伺服器 IP
  • state:連線狀態(應為 streaming
  • sent_lsn:已發送的 WAL 位置
  • write_lsn:從伺服器已寫入的 WAL 位置
  • flush_lsn:從伺服器已刷新的 WAL 位置
  • replay_lsn:從伺服器已重播的 WAL 位置

查看複製延遲

1
2
3
4
5
6
7
8
SELECT client_addr,
       state,
       sent_lsn,
       write_lsn,
       flush_lsn,
       replay_lsn,
       pg_wal_lsn_diff(sent_lsn, replay_lsn) AS replay_lag_bytes
FROM pg_stat_replication;

在從伺服器上檢查

確認複製狀態

1
sudo -u postgres psql -c "SELECT * FROM pg_stat_wal_receiver;"

確認是否處於復原模式

1
sudo -u postgres psql -c "SELECT pg_is_in_recovery();"

回傳 t 表示從伺服器正處於復原模式(正常運作中)。

測試資料同步

在主伺服器建立測試資料

1
sudo -u postgres psql
1
2
3
4
CREATE DATABASE testdb;
\c testdb
CREATE TABLE test_replication (id SERIAL PRIMARY KEY, data TEXT, created_at TIMESTAMP DEFAULT NOW());
INSERT INTO test_replication (data) VALUES ('Hello from Primary!');

在從伺服器驗證資料

1
sudo -u postgres psql -d testdb -c "SELECT * FROM test_replication;"

故障轉移

當主伺服器發生故障時,需要將從伺服器提升為新的主伺服器。

手動故障轉移

1. 確認主伺服器無法使用

確認主伺服器確實無法存取後再進行故障轉移。

2. 提升從伺服器

在從伺服器上執行:

1
sudo -u postgres pg_ctl promote -D /var/lib/postgresql/14/main

或使用 SQL 命令:

1
sudo -u postgres psql -c "SELECT pg_promote();"

3. 驗證提升成功

1
sudo -u postgres psql -c "SELECT pg_is_in_recovery();"

回傳 f 表示已不再處於復原模式,成為獨立的主伺服器。

4. 更新應用程式連線

將應用程式的資料庫連線指向新的主伺服器。

重新建立複製(原主伺服器恢復後)

當原主伺服器恢復後,可以將其轉換為從伺服器:

1
2
3
4
5
6
7
8
9
# 在原主伺服器上
sudo systemctl stop postgresql
sudo rm -rf /var/lib/postgresql/14/main/*

# 從新主伺服器複製資料
sudo -u postgres pg_basebackup -h 192.168.1.11 -U replicator -D /var/lib/postgresql/14/main -Fp -Xs -P -R

# 啟動服務
sudo systemctl start postgresql

監控與維護

監控複製延遲

建立監控查詢:

1
2
3
4
5
6
SELECT
    client_addr,
    state,
    pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS lag_bytes,
    pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) / 1024 / 1024 AS lag_mb
FROM pg_stat_replication;

設定警報

可搭配 Nagios、Zabbix 或 Prometheus 等監控工具,當複製延遲超過閾值時發出警報。

常見問題排除

複製連線失敗

  1. 檢查防火牆設定:
1
sudo ufw allow 5432/tcp
  1. 確認 pg_hba.conf 設定正確

  2. 測試網路連通性:

1
telnet 192.168.1.10 5432

WAL 檔案遺失

如果從伺服器落後太多,可能需要重新執行 pg_basebackup。建議適當調整 wal_keep_size 參數。

參考資料

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy