PostgreSQL在生产环境中部署高可用架构是数据库运维的基础工作。Patroni配合etcd实现自动故障转移,在主库故障时自动选举新主库并将读副本提升为主库,恢复时间控制在30秒以内。本文给出完整的搭建步骤和故障转移测试方法。
高可用架构设计与组件说明
架构由三个节点组成,每个节点运行PostgreSQL和Patroni实例。etcd集群(3节点)作为分布式配置存储,负责Leader选举和集群状态协调。HAProxy作为读写分离代理,应用通过HAProxy连接数据库。
架构拓扑:
HAProxy
(write:5432 read:5433)
|
+------------+------------+
| | |
PG-1 PG-2 PG-3
Leader Replica Replica
| | |
+------------+------------+
|
etcd集群
(3 nodes)
Patroni管理PostgreSQL生命周期,包括启动、停止、角色切换、复制配置。etcd存储集群拓扑信息(当前Leader、连接字符串、复制状态)。HAProxy通过Patroni REST API(端口8008)健康检查确定主库位置。
etcd集群搭建
三个节点分别安装etcd,配置集群发现。以三节点为例,IP为10.0.0.11、10.0.0.12、10.0.0.13。
# /etc/etcd/etcd.conf (节点1 - 10.0.0.11)
ETCD_NAME=node1
ETCD_DATA_DIR=/var/lib/etcd
ETCD_LISTEN_PEER_URLS=http://10.0.0.11:2380
ETCD_LISTEN_CLIENT_URLS=http://10.0.0.11:2379,http://127.0.0.1:2379
ETCD_INITIAL_ADVERTISE_PEER_URLS=http://10.0.0.11:2380
ETCD_ADVERTISE_CLIENT_URLS=http://10.0.0.11:2379
ETCD_INITIAL_CLUSTER=node1=http://10.0.0.11:2380,node2=http://10.0.0.12:2380,node3=http://10.0.0.13:2380
ETCD_INITIAL_CLUSTER_TOKEN=pg-cluster
ETCD_INITIAL_CLUSTER_STATE=new
# 启动etcd
systemctl enable etcd
systemctl start etcd
# 验证集群状态
etcdctl --endpoints=http://10.0.0.11:2379 member list
etcdctl --endpoints=http://10.0.0.11:2379 endpoint health --cluster
Patroni配置与PostgreSQL初始化
每个节点安装Patroni并配置YAML文件。关键配置项包括etcd连接、PostgreSQL参数、复制槽、自动故障转移策略。
# /etc/patroni/patroni.yml (节点1)
scope: pg-cluster
name: node1
restapi:
listen: 10.0.0.11:8008
connect_address: 10.0.0.11:8008
etcd:
hosts: 10.0.0.11:2379,10.0.0.12:2379,10.0.0.13:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 20
maximum_lag_on_failover: 1048576 # 1MB
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
wal_level: replica
hot_standby: "on"
max_wal_senders: 10
max_replication_slots: 10
wal_keep_size: 1024
archive_mode: "on"
archive_command: "cp %p /data/pg_archive/%f"
initdb:
- encoding: UTF8
- data-checksums
- locale: C
pg_hba:
- local all all trust
- host all all 10.0.0.0/24 md5
- host replication replicator 10.0.0.0/24 md5
postgresql:
listen: 0.0.0.0:5432
connect_address: 10.0.0.11:5432
data_dir: /data/pgdata
bin_dir: /usr/pgsql-16/bin
config_dir: /data/pgdata
pgpass: /tmp/pgpass
authentication:
replication:
username: replicator
password: RepPass2026
superuser:
username: postgres
password: PgSuper2026
create_replica_methods:
- basebackup
tags:
nofailover: false
noloadbalance: false
clonefrom: false
# 创建复制用户(在Leader节点执行)
psql -U postgres -c "CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'RepPass2026';"
# 启动Patroni(三个节点依次启动)
patroni /etc/patroni/patroni.yml &
# 查看集群状态
patronictl -c /etc/patroni/patroni.yml list
# 输出示例:
# + Cluster: pg-cluster ----+---------+----+-----------+
# | Member | Host | Role | State | TL |
# +---------+--------------+---------+----------+-----+
# | node1 | 10.0.0.11 | Leader | running | 1 |
# | node2 | 10.0.0.12 | Replica | streaming| 1 |
# | node3 | 10.0.0.13 | Replica | streaming| 1 |
# +---------+--------------+---------+----------+-----+
HAProxy读写分离配置
HAProxy通过Patroni REST API区分主库和副本。写请求路由到Leader,读请求分发到所有副本。
# /etc/haproxy/haproxy.cfg
frontend pg_write
bind *:5432
default_backend pg_primary
frontend pg_read
bind *:5433
default_backend pg_replicas
backend pg_primary
option httpchk
httpchk GET /primary
server node1 10.0.0.11:5432 check port 8008
server node2 10.0.0.12:5432 check port 8008
server node3 10.0.0.13:5432 check port 8008
backend pg_replicas
option httpchk
httpchk GET /replica
balance roundrobin
server node1 10.0.0.11:5432 check port 8008
server node2 10.0.0.12:5432 check port 8008
server node3 10.0.0.13:5432 check port 8008
Patroni REST API的/primary端点只在Leader节点返回200,/replica只在Replica节点返回200。HAProxy根据健康检查结果动态路由请求,故障转移后自动将写请求路由到新Leader。
故障转移测试与数据备份恢复
模拟主库故障,验证自动切换:
# 1. 停止Leader节点的PostgreSQL
ssh 10.0.0.11
systemctl stop patroni
# 2. 观察集群状态变化(10-30秒内完成切换)
patronictl -c /etc/patroni/patroni.yml list
# node1变为unreachable,node2或node3提升为Leader
# 3. 验证写入能力
psql -h 10.0.0.10 -p 5432 -U postgres -c "CREATE TABLE failover_test(id int);"
# 写入成功,证明新Leader已接管
# 4. 恢复原Leader
systemctl start patroni
# node1自动以Replica角色重新加入集群
# 5. 手动switchover(计划内维护)
patronictl switchover --candidate node2 --force
数据备份恢复配合pgBackRest实现增量备份和时间点恢复(PITR):
# pgBackRest配置
[db]
cmd=/usr/pgsql-16/bin/pgbackrest
stanza=pg-cluster
pg1-host=10.0.0.11
pg1-path=/data/pgdata
repo1-type=s3
repo1-s3-endpoint=s3.yunthe.com
repo1-s3-bucket=pg-backup
# 全量备份
pgbackrest --stanza=pg-cluster backup --type=full
# 增量备份
pgbackrest --stanza=pg-cluster backup --type=incr
# 时间点恢复示例(恢复到指定时间)
pgbackrest --stanza=pg-cluster restore \
--type=time --target="2026-07-24 14:30:00"
备份策略:每周日全量备份,每天增量备份,WAL日志持续归档。RPO(恢复点目标)控制在5分钟以内,RTO(恢复时间目标)在30分钟以内。
Patroni加etcd方案在三节点部署下能承受单节点故障而不中断服务。故障转移时间取决于ttl和loop_wait配置,默认配置下切换在20-30秒内完成。SQL查询优化方面,副本节点可承担只读查询压力,配合连接池(PgBouncer)进一步提升并发处理能力。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/postgresql-gao-ke-yong-jia-gou-da-jian-patronietcd-zi-dong/