PostgreSQL patroni高可用
PostgreSQL patroni 高可用 1:ectd 安裝和配置PostgreSQL patroni 高可用 2:patroni安裝和配置
PostgreSQL patroni 高可用 3:patroni 運維
PostgreSQL patroni 高可用 4:HAProxy和Keepalived實現讀寫分離
PostgreSQL patroni 高可用 2:patroni 安裝
圖片來源於:https://docs.percona.com/postgresql/12/solutions/high-availability.html#architecture-layout
1,服務器環境
2,patroni依賴包安裝
patroni是一個python開發的中間件,需要依賴python3環境以及python庫
Patroni[etcd] 表示Patroni 使用 etcd 作為分佈式配置存儲 (DCS)。
apt update
apt install -y libpq-dev python3-dev gcc
pip3 install -U pip setuptools wheel importlib_metadata
pip3 install -U psycopg2
pip3 install -U psycopg2-binary
pip3 install -U patroni[etcd]
安裝目錄
root@ubuntu08:/usr/local# whereis patroni
patroni: /usr/local/bin/patroni
3,創建patroni目錄
mkdir /usr/local/pgsql16/patroni
該目錄一定要授權給postgres用户,因為patroni是用postgres用户運行的,否則會導致後續無權限寫入
chown -R postgres:postgres /usr/local/pgsql16/patroni
chmod 700 -R /usr/local/pgsql16/patroni
4,編譯patroni配置文件patroni.yml
筆者在這裏卡了很久,而且實際測試中看,patroni.yml並不支持中文備註,如下配置文件中的中文註釋僅供參考,搭建環境是需移除
參考如下配置文件,patroni啓動的時候,會以如下文件為模板,將相關配置項寫入ectd數據庫中,同時會初始化一個數據庫。
需要注意的是:
在etcd的搭建過程中,etcd的配置文件中,是定義了集羣內所有成員的,也即如下
ETCD_INITIAL_CLUSTER="etcd01=http://192.168.152.115:2380,etcd02=http://192.168.152.116:2380,etcd03=http://192.168.152.117:2380",但是在patroni的配置文件,中並沒有指定PostgreSQL的主從信息,為什麼patroni啓動後,從節點會自動從主節點複製數據?
scope: pg_cluster_wy_prod
namespace: /service/
name: ubuntu08
restapi:
listen: 192.168.152.115:8008
connect_address: 192.168.152.115:8008
# 這裏一定要是etcd3
etcd3:
host: 192.168.152.115:2379
log:
level: INFO
traceback_level: ERROR
dir: /usr/local/pgsql16/patroni/
file_num: 10
file_size: 104857600
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
max_timelines_history: 0
master_start_timeout: 300
master_stop_timeout: 0
synchronous_mode: false
postgresql:
use_pg_rewind: true
pg_hba:
- host replication repl_user 0.0.0.0/0 md5
- host all all 0.0.0.0/0 md5
use_slots: true
parameters:
wal_level: hot_standby
hot_standby: "on"
max_connections: 100
max_worker_processes: 8
wal_keep_segments: 8
max_wal_senders: 10
max_replication_slots: 10
max_prepared_transactions: 0
max_locks_per_transaction: 64
wal_log_hints: "on"
track_commit_timestamp: "off"
archive_mode: "on"
archive_timeout: 1800s
archive_command: test ! -f /usr/local/pgsql16/pg_wal_arch/%f && cp %p /usr/local/pgsql16/pg_wal_arch/%f
log_destination: stderr
logging_collector: "on"
log_directory: "log"
log_filename: "postgresql-%Y-%m-%d_%H%M%S.log"
log_file_mode: "0600"
log_rotation_age: "1d"
log_min_duration_statement: 1
log_autovacuum_min_duration: 0
log_checkpoints: "on"
log_connections: "on"
log_disconnections: "on"
log_hostname: "on"
log_line_prefix: "%m [%p] user:%u,db:%d,app:%a,host:%h "
log_lock_waits: "on"
log_recovery_conflict_waits: "on"
log_statement: "ddl"
log_replication_commands: "on"
log_temp_files: 1
log_timezone: "Asia/Shanghai"
# some desired options for 'initdb'
initdb: # Note: It needs to be a list (some options need values, others are switches)
- encoding: UTF8
- data-checksums
postgresql:
listen: 192.168.152.115:9000
connect_address: 192.168.152.115:9000
data_dir: /usr/local/pgsql16/pg9000/data
bin_dir: /usr/local/pgsql16/server/bin
#config_dir:
pgpass: /home/postgres/.pgpass
# 用户名和密碼可以自定義
authentication:
replication:
username: repl_user
password: repl_user_123456
superuser:
username: postgres
password: postgres_pwd
rewind: # Has no effect on postgres 10 and lower
username: rewind_user
password: rewind_pwd
parameters:
unix_socket_directories: '..' # parent directory of data_dir
tags:
# failover_priority: 1
# sync_priority: 1
noloadbalance: false
clonefrom: false
nostream: false
Ubuntu09上的patroni配置文件,位置:/usr/local/pgsql16/patroni
Ubuntu09上的patroni配置文件scope: pg_cluster_wy_prod
namespace: /service/
name: ubuntu09
restapi:
listen: 192.168.152.116:8008
connect_address: 192.168.152.116:8008
etcd3:
host: 192.168.152.116:2379
log:
level: INFO
traceback_level: ERROR
dir: /usr/local/pgsql16/patroni/
file_num: 10
file_size: 104857600
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
max_timelines_history: 0
master_start_timeout: 300
master_stop_timeout: 0
synchronous_mode: false
postgresql:
use_pg_rewind: true
pg_hba:
- host replication repl_user 0.0.0.0/0 md5
- host all all 0.0.0.0/0 md5
use_slots: true
parameters:
wal_level: hot_standby
hot_standby: "on"
max_connections: 100
max_worker_processes: 8
wal_keep_segments: 8
max_wal_senders: 10
max_replication_slots: 10
max_prepared_transactions: 0
max_locks_per_transaction: 64
wal_log_hints: "on"
track_commit_timestamp: "off"
archive_mode: "on"
archive_timeout: 1800s
archive_command: test ! -f /usr/local/pgsql16/pg_wal_arch/%f && cp %p /usr/local/pgsql16/pg_wal_arch/%f
log_destination: stderr
logging_collector: "on"
log_directory: "log"
log_filename: "postgresql-%Y-%m-%d_%H%M%S.log"
log_file_mode: "0600"
log_rotation_age: "1d"
log_min_duration_statement: 1
log_autovacuum_min_duration: 0
log_checkpoints: "on"
log_connections: "on"
log_disconnections: "on"
log_hostname: "on"
log_line_prefix: "%m [%p] user:%u,db:%d,app:%a,host:%h "
log_lock_waits: "on"
log_recovery_conflict_waits: "on"
log_statement: "ddl"
log_replication_commands: "on"
log_temp_files: 1
log_timezone: "Asia/Shanghai"
# some desired options for 'initdb'
initdb: # Note: It needs to be a list (some options need values, others are switches)
- encoding: UTF8
- data-checksums
postgresql:
listen: 192.168.152.116:9000
connect_address: 192.168.152.116:9000
data_dir: /usr/local/pgsql16/pg9000/data
bin_dir: /usr/local/pgsql16/server/bin
#config_dir:
pgpass: /home/postgres/.pgpass
authentication:
replication:
username: repl_user
password: repl_user_123456
superuser:
username: postgres
password: postgres_pwd
rewind: # Has no effect on postgres 10 and lower
username: rewind_user
password: rewind_user_pwd
parameters:
unix_socket_directories: '..' # parent directory of data_dir
tags:
# failover_priority: 1
# sync_priority: 1
noloadbalance: false
clonefrom: false
nostream: false
Ubuntu10上的patroni配置文件,位置:/usr/local/pgsql16/patroni
Ubuntu10上的patroni配置文件scope: pg_cluster_wy_prod
namespace: /service/
name: ubuntu10
restapi:
listen: 192.168.152.117:8008
connect_address: 192.168.152.117:8008
etcd3:
host: 192.168.152.117:2379
log:
level: INFO
traceback_level: ERROR
dir: /usr/local/pgsql16/patroni/
file_num: 10
file_size: 104857600
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
max_timelines_history: 0
master_start_timeout: 300
master_stop_timeout: 0
synchronous_mode: false
postgresql:
use_pg_rewind: true
pg_hba:
- host replication repl_user 0.0.0.0/0 md5
- host all all 0.0.0.0/0 md5
use_slots: true
parameters:
wal_level: hot_standby
hot_standby: "on"
max_connections: 100
max_worker_processes: 8
wal_keep_segments: 8
max_wal_senders: 10
max_replication_slots: 10
max_prepared_transactions: 0
max_locks_per_transaction: 64
wal_log_hints: "on"
track_commit_timestamp: "off"
archive_mode: "on"
archive_timeout: 1800s
archive_command: test ! -f /usr/local/pgsql16/pg_wal_arch/%f && cp %p /usr/local/pgsql16/pg_wal_arch/%f
log_destination: stderr
logging_collector: "on"
log_directory: "log"
log_filename: "postgresql-%Y-%m-%d_%H%M%S.log"
log_file_mode: "0600"
log_rotation_age: "1d"
log_min_duration_statement: 1
log_autovacuum_min_duration: 0
log_checkpoints: "on"
log_connections: "on"
log_disconnections: "on"
log_hostname: "on"
log_line_prefix: "%m [%p] user:%u,db:%d,app:%a,host:%h "
log_lock_waits: "on"
log_recovery_conflict_waits: "on"
log_statement: "ddl"
log_replication_commands: "on"
log_temp_files: 1
log_timezone: "Asia/Shanghai"
# some desired options for 'initdb'
initdb: # Note: It needs to be a list (some options need values, others are switches)
- encoding: UTF8
- data-checksums
postgresql:
listen: 192.168.152.117:9000
connect_address: 192.168.152.117:9000
data_dir: /usr/local/pgsql16/pg9000/data
bin_dir: /usr/local/pgsql16/server/bin
#config_dir:
pgpass: /home/postgres/.pgpass
authentication:
replication:
username: repl_user
password: repl_user_123456
superuser:
username: postgres
password: postgres_pwd
rewind: # Has no effect on postgres 10 and lower
username: rewind_user
password: rewind_user_pwd
parameters:
unix_socket_directories: '..' # parent directory of data_dir
tags:
# failover_priority: 1
# sync_priority: 1
noloadbalance: false
clonefrom: false
nostream: false
4.1 相關參數
scope: pg_cluster_wy_prod
root@ubuntu08:/usr/local# etcdctl get /service --prefix --keys-only
{"level":"warn","ts":"2025-09-22T16:47:36.675953+0800","caller":"flags/flag.go:94","msg":"unrecognized environment variable","environment-variable":"ETCDCTL_API=3"}
/service/pg_cluster_wy_prod/config
/service/pg_cluster_wy_prod/history
/service/pg_cluster_wy_prod/initialize
/service/pg_cluster_wy_prod/leader
/service/pg_cluster_wy_prod/members/ubuntu08
/service/pg_cluster_wy_prod/members/ubuntu09
/service/pg_cluster_wy_prod/members/ubuntu10
/service/pg_cluster_wy_prod/status
5,編輯patroni systemctl服務文件
patroni的systemctl 啓動文件,各個節點都一樣
[Unit]
Description=patroni
After=network.target remote-fs.target nss-lookup.target etcd.service #一定要等到etcd啓動之後再啓動patroni
Requires=etcd.service
[Service]
Type=forking
User=postgres
Group=postgres
Environment="PGHOME=/usr/local/pgsql16/server"
Environment="PGDATA=/usr/local/pgsql16/pg9000/data"
Environment="PGPORT=9000"
Environment="LD_LIBRARY_PATH=/usr/local/pgsql16/server/lib"
Environment="PATH=/usr/local/pgsql16/server/bin:/usr/local/bin"
ExecStart=/bin/bash -c "patroni /usr/local/pgsql16/patroni/patroni.yml >> /usr/local/pgsql16/patroni/patroni.log 2>&1 &"
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/usr/bin/killall patroni
KillMode=process
TimeoutSec=30
Restart=no
[Install]
WantedBy=multi-user.target
6,啓動partoni
設置自動啓動,並啓動服務,檢查集羣狀態,patronictl -c /usr/local/pgsql16/patroni/patroni.yml list
systemctl daemon-reload
systemctl start patroni
systemctl enable patroni
root@ubuntu08:/usr/local# patronictl -c /usr/local/pgsql16/patroni/patroni.yml list
+ Cluster: pg_cluster_wy_prod (7552796412810163150) +-----------+
| Member | Host | Role | State | TL | Lag in MB |
+----------+----------------+--------+---------+----+-----------+
| ubuntu08 | 127.0.0.1:9000 | Leader | running | 1 | |
+----------+----------------+--------+---------+----+-----------+
root@ubuntu08:/usr/local#
root@ubuntu08:/usr/local# systemctl status patroni
● patroni.service - patroni
Loaded: loaded (/etc/systemd/system/patroni.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2025-09-22 14:27:29 CST; 42min ago
Main PID: 623548 (patroni)
Tasks: 13 (limit: 4550)
Memory: 95.6M
CGroup: /system.slice/patroni.service
├─623548 /usr/bin/python3 /usr/local/bin/patroni /usr/local/pgsql16/patroni/patroni.yml
├─623575 /usr/local/pgsql16/server/bin/postgres -D /usr/local/pgsql16/pg9000/data --config-file=/usr/local/pgsql16/pg9000/data/postgresql.conf --listen_addresses=127.0.0.1 --port=9000 --cluster>
├─623577 postgres: pg_cluster_wy_prod: checkpointer
├─623578 postgres: pg_cluster_wy_prod: background writer
├─623580 postgres: pg_cluster_wy_prod: walwriter
├─623581 postgres: pg_cluster_wy_prod: autovacuum launcher
├─623583 postgres: pg_cluster_wy_prod: logical replication launcher
└─623588 postgres: pg_cluster_wy_prod: postgres postgres 127.0.0.1(48710) idle
Sep 22 14:27:29 ubuntu08 systemd[1]: Starting patroni...
Sep 22 14:27:29 ubuntu08 systemd[1]: Started patroni.
--查看patroni集羣狀態
root@ubuntu08:/usr/local# patronictl -c /usr/local/pgsql16/patroni/patroni.yml list
+ Cluster: pg_cluster_wy_prod (7552796412810163150) +-----------+
| Member | Host | Role | State | TL | Lag in MB |
+----------+----------------+--------+---------+----+-----------+
| ubuntu08 | 127.0.0.1:9000 | Leader | running | 1 | |
+----------+----------------+--------+---------+----+-----------+
root@ubuntu08:/usr/local#
root@ubuntu08:/usr/local#
patroni環境變量配置,這樣不需要patronictl 每次都加上-c /usr/local/pgsql16/patroni/patroni.yml 來指定配置文件
為了方便日常操作,添加以下內容到/etc/profile中
vi /etc/profile
export PATRONICTL_CONFIG_FILE=/home/postgres/patroni/patroni.yml
source /etc/profile
7,patroni環境下修改PostgreSQL配置文件
這部分非常非常非常重要,很容易誤解,筆者在這裏花了一個多小時的時間,來測試各種場景。
方法1 patronictl edit-config
方法2 ALTER SYSTEM SET 命令
--在從節點上執行
SHOW listen_addresses;
listen_addresses|
----------------+
192.168.152.115 |
--查看當前work_mem
show work_mem;
work_mem|
--------+
4MB |
--修改work_mem
ALTER SYSTEM SET work_mem TO '8MB';
SELECT pg_reload_conf();