PostgreSQL高可用的三种方案对比
数据库运维中,高可用架构是保证业务连续性的关键。PostgreSQL原生支持流复制(Streaming Replication),相比MySQL的主从复制,它在同步策略和数据一致性上有更精细的控制。三种常见的高可用方案:流复制+Keepalived、流复制+Patroni、逻辑复制+Citus,各有适用场景。
流复制+Keepalived适合2节点小集群,配置简单但故障切换需要人工介入或脚本触发。流复制+Patroni支持多节点自动选举,是目前最推荐的生产方案。逻辑复制+Citus适合需要多写多活的分布式场景。本文聚焦流复制+Patroni方案的完整配置。
流复制基础:主节点配置
流复制要求PostgreSQL版本一致,且主从节点的数据目录通过pg_basebackup初始化。
-- 主节点postgresql.conf配置
wal_level = replica
max_wal_senders = 10
max_replication_slots = 10
hot_standby = on
wal_keep_size = 1024MB
archive_mode = on
archive_command = 'cp %p /data/pg_archive/%f'
-- 主节点pg_hba.conf允许复制连接
host replication replicator 10.0.0.0/8 md5
-- 创建复制专用用户
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'secure_password';
-- 创建复制槽(防止从节点断连后WAL被删除)
SELECT pg_create_physical_replication_slot('replica_1');
wal_level设为replica才能支持流复制。max_wal_senders定义最大从节点连接数。wal_keep_size保留最近的WAL段,防止从节点短暂断连后需要从头同步。复制槽(Replication Slot)是更可靠的WAL保留机制,从节点断连后主节点不会删除对应WAL。
从节点初始化与配置
# 使用pg_basebackup从主节点同步初始数据
pg_basebackup -h 10.0.1.10 -U replicator -D /data/pgdata -Fp -Xs -P -R
# -R参数自动创建standby.signal和primary_conninfo配置
# 从节点postgresql.conf
hot_standby = on
hot_standby_feedback = on
max_standby_streaming_delay = 30s
# 自动生成的postgresql.auto.conf内容如下:
# primary_conninfo = 'host=10.0.1.10 port=5432 user=replicator password=secure_password'
# primary_slot_name = 'replica_1'
# 启动从节点
pg_ctl -D /data/pgdata start
# 验证复制状态(主节点执行)
SELECT * FROM pg_stat_replication;
SELECT * FROM pg_replication_slots;
hot_standby_feedback让从节点将自身查询状态反馈给主节点,避免主节点清理从节点正在使用的行版本。pg_stat_replication视图可以查看从节点的同步状态和延迟。
同步复制与异步复制选择
PostgreSQL支持多种同步级别,在生产环境中需要根据数据安全性和性能需求选择:
-- 异步复制(默认,性能优先)
synchronous_commit = off
-- 同步复制(数据安全优先)
synchronous_commit = on
synchronous_standby_names = 'FIRST 1 (replica_1, replica_2)'
-- remote_write模式(折中方案)
synchronous_commit = remote_write
synchronous_standby_names = 'ANY 1 (replica_1, replica_2)'
FIRST 1表示列表中第一个可用从节点同步确认即可提交。ANY 1表示任意一个从节点确认即可。remote_write模式下从节点写入操作系统缓冲区即返回确认,性能优于remote_flush但极端情况下可能丢失最后几条事务。
Patroni自动故障切换配置
Patroni是PostgreSQL高可用的自动化管理工具,基于分布式一致性(etcd或Consul)实现主节点选举:
# patroni.yml配置文件
scope: pg_cluster
namespace: /service/
name: node1
restapi:
listen: 0.0.0.0:8008
connect_address: 10.0.1.10:8008
etcd:
hosts: 10.0.1.100:2379,10.0.1.101:2379,10.0.1.102:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 20
maximum_lag_on_failover: 1048576
synchronous: true
postgresql:
use_pg_rewind: true
parameters:
wal_level: replica
hot_standby: on
max_wal_senders: 10
max_replication_slots: 10
wal_keep_size: 1024MB
initdb:
- encoding: UTF8
- data-checksums
postgresql:
bin_dir: /usr/lib/postgresql/15/bin
data_dir: /data/pgdata
config_dir: /data/pgdata
listen: 0.0.0.0:5432
connect_address: 10.0.1.10:5432
authentication:
replication:
username: replicator
password: secure_password
superuser:
username: postgres
password: admin_password
rewind:
username: rewind_user
password: rewind_password
pg_hba:
- host replication replicator 10.0.0.0/8 md5
- host all all 0.0.0.0/0 md5
watchdog:
mode: automatic
device: /dev/watchdog
safety_margin: 5
maximum_lag_on_failover定义故障切换时允许的最大WAL延迟(字节),超过此值则不执行切换。use_pg_rewind允许原主节点恢复后通过pg_rewind重新加入集群,而不需要全量基础备份。watchdog是硬件级别的安全机制,Patroni进程卡死时触发系统重启。
HAProxy健康检查与VIP切换
Patroni配合HAProxy实现读写分离和VIP自动切换:
# haproxy.cfg
frontend pg_frontend
bind *:5432
mode tcp
default_backend pg_backend
backend pg_backend
mode tcp
option tcp-check
tcp-check send PING\r\n
tcp-check expect string PRIMARY
server node1 10.0.1.10:5432 check port 8008 inter 3s rise 2 fall 3
server node2 10.0.1.11:5432 check port 8008 inter 3s rise 2 fall 3
server node3 10.0.1.12:5432 check port 8008 inter 3s rise 2 fall 3
# 只读后端(所有从节点+主节点)
backend pg_readonly
mode tcp
option tcp-check
tcp-check send PING\r\n
tcp-check expect string ACCEPT
server node1 10.0.1.10:5432 check port 8008
server node2 10.0.1.11:5432 check port 8008
server node3 10.0.1.12:5432 check port 8008
Patroni的REST API在8008端口暴露健康检查端点。/primary返回200表示主节点,/replica返回200表示从节点。HAProxy根据检查结果动态将写请求路由到主节点,读请求分发到所有节点。数据迁移实战中,从旧架构切换到Patroni集群需要先搭建新集群,通过逻辑复制订阅旧库变更,校验数据一致后切换VIP。SQL查询优化在高可用环境下还需要考虑只读节点的查询路由,避免读取到尚未同步的数据。数据备份恢复方案在高可用集群中应基于PITR(时间点恢复)配置,通过WAL归档实现任意时间点的数据恢复。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/postgresql-gao-ke-yong-jia-gou-shi-zhan-liu-fu-zhi-pei-zhi/