PostgreSQL高可用架构通过流复制和自动故障转移机制,在主库故障时实现秒级切换到备库,是数据库运维中保障数据可靠性和服务连续性的核心方案。Patroni作为PostgreSQL高可用管理工具,配合etcd实现集群协调,已成为PostgreSQL生产部署的事实标准。
PostgreSQL流复制原理与配置
PostgreSQL流复制(Streaming Replication)基于WAL(Write-Ahead Log)机制,主库将WAL日志实时传输到备库,备库重放日志保持数据同步。配置流复制需要修改主库postgresql.conf和pg_hba.conf:
# 主库 postgresql.conf
wal_level = replica
max_wal_senders = 10
wal_keep_size = 1024 # 保留1GB WAL日志,避免备库断连后需要全量同步
hot_standby = on
synchronous_commit = on # 同步提交,确保数据零丢失
# 主库 pg_hba.conf - 允许备库连接
host replication replicator 192.168.1.0/24 md5
# 创建复制用户
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'secure_pwd';
# 备库使用pg_basebackup初始化
pg_basebackup -h 192.168.1.10 -U replicator -D /var/lib/postgresql/data \
-Fp -Xs -P -R
# -R 自动创建standby.signal和primary_conninfo配置
# 备库 postgresql.auto.conf
primary_conninfo = 'host=192.168.1.10 port=5432 user=replicator password=secure_pwd'
hot_standby = on
hot_standby_feedback = on # 防止备库长查询被主库vacuum中断
流复制有异步和同步两种模式。异步复制(默认)主库提交不等备库确认,性能高但可能丢失少量最新数据。同步复制主库等待至少一个备库确认收到WAL后才提交,保证数据零丢失,但会增加写入延迟。生产环境建议采用同步复制配合本地异步复制的多级架构。
Patroni集群部署与协调配置
Patroni管理PostgreSQL集群的生命周期,通过etcd(或Consul/ZooKeeper)存储集群元数据和进行Leader选举。每个PostgreSQL节点运行一个Patroni进程:
# patroni.yml (node-1)
scope: pg-cluster
name: node-1
restapi:
listen: 0.0.0.0:8008
connect_address: 192.168.1.10:8008
etcd:
hosts: 192.168.1.20:2379,192.168.1.21:2379,192.168.1.22:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 20
maximum_lag_on_failover: 1048576 # 1MB,超过此延迟不允许故障转移
synchronous_mode: true
postgresql:
parameters:
wal_level: replica
max_wal_senders: 10
wal_keep_size: 1024
hot_standby: on
synchronous_commit: on
postgresql:
listen: 0.0.0.0:5432
connect_address: 192.168.1.10:5432
data_dir: /var/lib/postgresql/data
bin_dir: /usr/lib/postgresql/15/bin
authentication:
replication:
username: replicator
password: secure_pwd
superuser:
username: postgres
password: super_secure_pwd
tags:
nofailover: false
noloadbalance: false
clonefrom: false
sync_standby: true # 标记为同步备库候选
Patroni的关键参数:ttl=30表示Leader租约30秒,超时未续约触发选举;loop_wait=10表示每10秒检查一次集群状态;maximum_lag_on_failover限制故障转移时备库最大允许的复制延迟,防止切换到数据落后的节点。
自动故障转移流程与选举机制
当主库故障时,Patroni的故障转移流程如下:
- 主库Patroni停止心跳,etcd中Leader租约过期(30秒后)
- 备库Patroni检测到Leader丢失,发起选举
- 选举获胜条件:WAL接收位置最靠前、且复制延迟在maximum_lag_on_failover范围内
- 新Leader执行promote提升为主库,更新etcd中的Leader信息
- 其他备库自动指向新主库,重新建立流复制连接
# 查看集群状态
patronictl list
# +---------+--------+------------+----+-----------+
# | Member | Host | Role | TL | Lag in MB |
# +---------+--------+------------+----+-----------+
# | node-1 | 10.0.1.10 | Leader | 15 | |
# | node-2 | 10.0.1.11 | Replica | 15 | 0 |
# | node-3 | 10.0.1.12 | Sync | 15 | 0 |
# +---------+--------+------------+----+-----------+
# 手动切换(维护场景)
patronictl switchover pg-cluster
# 确认后Patroni将当前Leader降级为Replica,提升指定备库为新Leader
# 查看集群配置
patronictl show-config pg-cluster
同步模式下,Patroni确保始终有一个同步备库(Sync角色),只有同步备库才有资格在故障转移时成为新Leader,保证数据零丢失。但同步模式下如果同步备库也宕机,主库会降级为异步模式继续运行(取决于synchronous_mode_strict设置)。
HAProxy负载均衡与读写分离
Patroni提供REST API用于健康检查,结合HAProxy实现读写分离。应用写请求到主库,读请求分发到备库:
# haproxy.cfg
frontend pg_write
bind *:5432
default_backend pg_master
frontend pg_read
bind *:5433
default_backend pg_replicas
backend pg_master
option httpchk
http-check expect status 200
default-server inter 3s fall 3 rise 2
server node-1 192.168.1.10:5432 check port 8008
server node-2 192.168.1.11:5432 check port 8008
server node-3 192.168.1.12:5432 check port 8008
# Patroni返回200表示Leader,503表示非Leader
# HAProxy只会将请求路由到返回200的节点
backend pg_replicas
balance roundrobin
option httpchk
http-check expect status 200
default-server inter 3s fall 3 rise 2
server node-1 192.168.1.10:5432 check port 8008
server node-2 192.168.1.11:5432 check port 8008
server node-3 192.168.1.12:5432 check port 8008
# 需要配置Patroni返回200给Replica角色
# 在Patroni的restapi中配置:
# standby_cluster: null (Leader返回200)
# 或使用tags: nofailover: true (非Leader也返回200)
HAProxy通过Patroni的8008端口健康检查接口判断节点角色。Leader节点返回HTTP 200,Replica节点返回HTTP 503(默认)。写端口5432只会路由到Leader,读端口5433通过roundrobin分发到所有Replica。故障转移时,HAProxy自动检测到新Leader并切换写流量,整个切换过程对应用透明。
集群监控与日常运维要点
PostgreSQL高可用集群的监控指标包括:复制延迟(pg_stat_replication中的sent_lsn/replay_lsn差值)、连接数(pg_stat_activity)、WAL生成速率、缓存命中率、慢查询。使用Prometheus + postgres_exporter采集指标:
# postgres_exporter配置
DATA_SOURCE_NAME="postgresql://monitor:monitor_pwd@localhost:5432/postgres?sslmode=disable"
# 关键PromQL查询
# 复制延迟(字节)
pg_replication_lag_bytes = pg_stat_replication_pg_wal_lsn - pg_stat_replication_pg_replay_lsn
# 复制延迟(秒)
pg_replication_lag_seconds = time() - pg_stat_replication_pg_replay_timestamp
# 连接数使用率
pg_connections_ratio = pg_stat_activity_count / pg_settings_max_connections
日常运维中需要定期验证故障转移功能。在维护窗口执行patronictl switchover测试主备切换是否正常,检查应用连接是否自动恢复。WAL归档配置(archive_mode=on + archive_command)确保WAL日志持久化到对象存储,用于时间点恢复(PITR)。定期执行pg_dump逻辑备份作为物理复制的补充,防止逻辑损坏(如误删表)导致数据丢失。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/postgresql-gao-ke-yong-jia-gou-da-jian-shi-zhan-liu-fu-zhi/