1. Patroni高可用架构解析
PostgreSQL作为企业级开源数据库,在生产环境中部署高可用方案是基本要求。Patroni作为目前最成熟的PostgreSQL高可用解决方案之一,其架构设计充分考虑了自动化运维和故障恢复的需求。
Patroni的核心架构由三个关键组件构成:
- PostgreSQL数据库实例:运行实际的数据库服务
- Patroni守护进程:负责监控和管理PostgreSQL实例
- 分布式配置存储(DCS):如etcd、ZooKeeper或Consul,用于集群状态管理
这种架构设计使得Patroni能够实现:
- 自动故障检测和主从切换(failover)
- 自动修复故障节点
- 动态配置管理
- 客户端透明访问
关键提示:生产环境部署时,DCS组件(如etcd)必须部署为集群模式,单节点etcd会成为整个高可用架构的单点故障源。
2. 环境准备与基础部署
2.1 系统环境配置
在CentOS 7.8系统上部署Patroni集群前,需要进行以下基础配置:
bash复制# 时钟同步配置
yum install -y ntpdate
ntpdate time.windows.com && hwclock -w
# 关闭防火墙和SELinux
setenforce 0
sed -i.bak "s/SELINUX=enforcing/SELINUX=permissive/g" /etc/selinux/config
systemctl disable firewalld.service
systemctl stop firewalld.service
iptables -F
2.2 软件包安装
安装PostgreSQL 12和Patroni所需依赖:
bash复制# 安装PostgreSQL 12
yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
yum install -y postgresql12-server postgresql12-contrib
# 安装Patroni及其依赖
yum install -y gcc epel-release python-pip python-psycopg2 python-devel
pip install --upgrade pip
pip install --upgrade setuptools
pip install patroni[etcd]
2.3 目录结构与权限配置
bash复制# 创建数据目录
mkdir -p /pgsql/data
chown postgres:postgres -R /pgsql
chmod -R 700 /pgsql/data
# 配置环境变量
echo 'export PGDATA=/pgsql/data' >> ~postgres/.bash_profile
echo 'export PATH=/usr/pgsql-12/bin:$PATH' >> ~postgres/.bash_profile
echo 'export PATRONICTL_CONFIG_FILE=/etc/patroni.yml' > /etc/profile.d/patroni.sh
3. Patroni集群配置详解
3.1 基础配置文件
典型的Patroni配置文件(/etc/patroni.yml)示例如下:
yaml复制scope: pgsql
namespace: /service/
name: pg1
restapi:
listen: 0.0.0.0:8008
connect_address: 192.168.234.201:8008
etcd:
host: 192.168.234.204:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
master_start_timeout: 300
synchronous_mode: false
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
listen_addresses: "0.0.0.0"
port: 5432
wal_level: logical
hot_standby: "on"
wal_keep_segments: 100
max_wal_senders: 10
max_replication_slots: 10
wal_log_hints: "on"
initdb:
- encoding: UTF8
- locale: C
- lc-ctype: zh_CN.UTF-8
- data-checksums
pg_hba:
- host replication repl 0.0.0.0/0 md5
- host all all 0.0.0.0/0 md5
postgresql:
listen: 0.0.0.0:5432
connect_address: 192.168.234.201:5432
data_dir: /pgsql/data
bin_dir: /usr/pgsql-12/bin
authentication:
replication:
username: repl
password: "123456"
superuser:
username: postgres
password: "123456"
basebackup:
max-rate: 100M
checkpoint: fast
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false
3.2 关键参数解析
-
ttl和loop_wait:
- ttl(30秒):Leader锁的存活时间
- loop_wait(10秒):Patroni检查集群状态的间隔
- 这两个参数共同决定了故障检测的灵敏度
-
use_pg_rewind:
- 启用后允许旧主库在重新加入集群时自动同步数据
- 比完全重建备库更高效
-
synchronous_mode:
- 设置为true时启用同步复制
- 提供更强的数据一致性保证
经验之谈:生产环境中,建议将wal_keep_segments设置为至少100,避免备库因WAL日志缺失而需要完全重建。
4. 脑裂防护机制
4.1 脑裂风险场景
Patroni通过多种机制防止脑裂(多个节点同时认为自己是主库):
-
DCS(etcd)仲裁:
- 只有持有DCS中Leader锁的节点才能成为主库
- 当节点无法连接DCS时,会自动降级为备库
-
Watchdog设备:
- 配置Linux watchdog设备监控Patroni进程
- 当Patroni异常时自动重启服务器
4.2 Watchdog配置
在/etc/patroni.yml中添加:
yaml复制watchdog:
mode: automatic
device: /dev/watchdog
safety_margin: 5
对应的systemd服务配置(/etc/systemd/system/patroni.service):
ini复制[Unit]
Description=Runners to orchestrate a high-availability PostgreSQL
After=syslog.target network.target
[Service]
Type=simple
User=postgres
Group=postgres
ExecStartPre=-/usr/bin/sudo /sbin/modprobe softdog
ExecStartPre=-/usr/bin/sudo /bin/chown postgres /dev/watchdog
ExecStart=/usr/bin/patroni /etc/patroni.yml
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=process
TimeoutSec=30
Restart=no
[Install]
WantedBy=multi-user.target
4.3 同步复制防护
配置同步复制提供最强的脑裂防护:
yaml复制synchronous_mode: true
synchronous_mode_strict: true # 禁止自动降级为异步复制
这种模式下:
- 主库必须有至少一个同步备库才能接受写入
- 当同步备库不可用时,主库会停止服务而非降级
- 完全避免"双主"情况下的数据不一致
实测建议:同步复制模式会降低写入性能,在性能敏感场景可考虑使用synchronous_mode: true但不启用strict模式,允许临时降级为异步复制。
5. 客户端访问方案
5.1 多主机URL连接
PostgreSQL驱动支持在连接字符串中指定多个主机:
JDBC连接示例:
java复制jdbc:postgresql://192.168.234.201:5432,192.168.234.202:5432/postgres?targetServerType=primary
libpq连接示例:
bash复制psql "host=192.168.234.201,192.168.234.202 port=5432 dbname=postgres target_session_attrs=read-write"
5.2 VIP漂移方案
通过Patroni回调脚本实现VIP自动漂移:
- 创建VIP管理脚本/pgsql/loadvip.sh:
bash复制#!/bin/bash
VIP=192.168.234.210
GATEWAY=192.168.234.2
DEV=ens33
action=$1
role=$2
cluster=$3
load_vip() {
ip a|grep -w ${DEV}|grep -w ${VIP} >/dev/null || {
sudo ip addr add ${VIP}/32 dev ${DEV} &&
arping -U -I ${DEV} -s ${VIP} ${GATEWAY} -c 5
}
}
unload_vip() {
ip a|grep -w ${DEV}|grep -w ${VIP} >/dev/null &&
sudo ip addr del ${VIP}/32 dev ${DEV}
}
case $action in
on_start|on_restart|on_role_change)
case $role in
master) load_vip ;;
replica) unload_vip ;;
esac ;;
esac
- 在Patroni配置中添加回调:
yaml复制postgresql:
callbacks:
on_start: /bin/bash /pgsql/loadvip.sh
on_restart: /bin/bash /pgsql/loadvip.sh
on_role_change: /bin/bash /pgsql/loadvip.sh
5.3 HAProxy负载均衡
HAProxy配置示例(/etc/haproxy/haproxy.cfg):
ini复制listen pgsql
bind *:5000
option httpchk
http-check expect status 200
default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
server pg1 192.168.234.201:5432 check port 8008
server pg2 192.168.234.202:5432 check port 8008
listen pgsql_read
bind *:6000
option httpchk GET /replica
http-check expect status 200
default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
server pg1 192.168.234.201:5432 check port 8008
server pg2 192.168.234.202:5432 check port 8008
6. 日常运维操作
6.1 集群状态监控
bash复制# 查看集群状态
patronictl -c /etc/patroni.yml list
# 输出示例:
+ Cluster: pgsql (6868912301204081018) -------+----+-----------+
| Member | Host | Role | State | TL | Lag in MB |
+--------+-----------------+--------+---------+----+-----------+
| pg1 | 192.168.234.201 | Leader | running | 1 | |
| pg2 | 192.168.234.202 | | running | 1 | 0.0 |
+--------+-----------------+--------+---------+----+-----------+
6.2 配置动态修改
bash复制# 修改集群配置
patronictl -c /etc/patroni.yml edit-config
# 常见修改项示例:
- 修改max_connections
- 调整shared_buffers
- 开启/关闭同步复制
6.3 主从切换操作
计划内切换(switchover):
bash复制patronictl -c /etc/patroni.yml switchover
故障转移(failover):
bash复制patronictl -c /etc/patroni.yml failover
6.4 节点维护
bash复制# 重启特定节点
patronictl -c /etc/patroni.yml restart pgsql pg1
# 重新初始化节点
patronictl -c /etc/patroni.yml reinit pgsql pg2
7. 故障排查技巧
7.1 常见问题诊断
-
节点无法加入集群:
- 检查DCS连接是否正常
- 验证复制用户权限
- 查看PostgreSQL日志中的错误信息
-
主从切换失败:
- 检查备库的WAL接收状态
- 验证网络连通性
- 检查DCS中的Leader锁状态
-
VIP漂移异常:
- 验证回调脚本执行权限
- 检查ARP缓存更新情况
- 查看系统日志中的网络错误
7.2 日志分析要点
-
Patroni日志:
- 位于/var/log/messages或journalctl -u patroni
- 关注Leader选举相关消息
-
PostgreSQL日志:
- 位于$PGDATA/pg_log/
- 关注复制状态变化和错误信息
-
etcd日志:
- 位于/var/log/messages或journalctl -u etcd
- 检查集群健康状态
8. 性能优化建议
8.1 复制参数调优
yaml复制postgresql:
parameters:
max_wal_senders: 10
wal_keep_segments: 100
max_replication_slots: 10
synchronous_commit: remote_apply # 强一致性场景
8.2 监控指标配置
关键监控指标包括:
- 复制延迟(lag in bytes)
- DCS响应时间
- 主从切换次数
- 数据库负载指标
8.3 备份策略
结合Patroni的备份工具集成:
yaml复制bootstrap:
dcs:
postgresql:
create_replica_methods:
- basebackup
- wal_e
- pgbackrest
9. 生产环境注意事项
-
DCS部署:
- etcd集群至少3节点
- 跨机架/可用区部署
- 定期备份etcd数据
-
网络配置:
- 确保节点间低延迟
- 配置冗余网络路径
- 监控网络抖动情况
-
容量规划:
- 预留足够的WAL存储空间
- 监控磁盘使用情况
- 规划垂直/水平扩展方案
-
安全加固:
- 加密复制流量
- 限制DCS访问权限
- 定期轮换数据库密码
10. 版本升级策略
10.1 滚动升级步骤
-
暂停Patroni自动故障转移:
bash复制
patronictl pause -
逐个节点升级:
- 停止Patroni服务
- 升级PostgreSQL软件包
- 启动Patroni服务
-
恢复自动故障转移:
bash复制
patronictl resume
10.2 主要版本升级
对于PostgreSQL主版本升级(如11→12):
- 使用逻辑复制工具(pg_dump/pg_restore)
- 或使用pg_upgrade工具
- 创建新的Patroni集群
- 迁移应用连接
升级前务必在测试环境充分验证,并准备回滚方案。
