外观
PostgreSQL 基于 repmgr 的高可用方案
repmgr 是一个功能强大的 PostgreSQL 复制管理和高可用解决方案,它专注于简化主从复制的部署、管理和故障转移过程。repmgr 提供了主从复制的自动监控、故障检测和手动/自动故障转移功能,同时还提供了详细的节点状态报告和复制拓扑可视化。本文将详细介绍如何使用 repmgr 实现 PostgreSQL 的高可用架构,兼顾不同 PostgreSQL 版本和 repmgr 版本的特性差异。
repmgr 架构概述
repmgr 核心组件
repmgr 架构主要由以下组件组成:
- repmgrd:repmgr 守护进程,运行在每个 PostgreSQL 节点上,负责监控节点状态和处理故障转移
- repmgr CLI:命令行工具,用于管理复制集群、执行故障转移和生成状态报告
- PostgreSQL 实例:集群中的主库和从库实例
- repmgr 元数据:存储在专用数据库中的集群配置和状态信息
repmgr 工作原理
- 集群初始化:在主库上初始化 repmgr 元数据库,注册主库信息
- 从库注册:在从库上执行 repmgr 注册命令,连接到主库并创建复制关系
- 健康监控:repmgrd 守护进程定期检查本地 PostgreSQL 实例的健康状态,并将状态信息更新到元数据库
- 故障检测:repmgrd 通过监控元数据库中的状态信息,检测主库故障
- 故障转移:当主库故障时,repmgr 可以手动或自动将一个从库提升为主库
- 集群重配置:其他从库会自动重新配置,连接到新的主库
repmgr 与 Patroni 的比较
| 特性 | repmgr | Patroni |
|---|---|---|
| 架构复杂度 | 简单 | 较复杂 |
| 依赖 | 仅 PostgreSQL | 分布式一致性存储(etcd/Consul/ZooKeeper) |
| 自动故障转移 | 支持 | 支持 |
| 配置管理 | 有限 | 强大 |
| 复制拓扑 | 支持级联复制 | 支持 |
| 社区活跃度 | 活跃 | 非常活跃 |
| 学习曲线 | 平缓 | 较陡峭 |
| 适用场景 | 中小型集群 | 大型集群 |
环境准备
硬件要求
| 组件 | 最低配置 | 推荐配置 |
|---|---|---|
| CPU | 2 核 | 4 核或以上 |
| 内存 | 4 GB | 8 GB 或以上 |
| 存储 | 100 GB SSD | 200 GB NVMe SSD |
| 网络 | 千兆以太网 | 万兆以太网 |
软件要求
| 软件 | 版本要求 | 说明 |
|---|---|---|
| PostgreSQL | 10 或以上 | PostgreSQL 13+ 对 repmgr 的支持更好 |
| repmgr | 5.3 或以上 | repmgr 5.x 支持 PostgreSQL 10+,repmgr 6.x 支持 PostgreSQL 11+ |
节点规划
本示例将部署一个包含 3 个节点的 repmgr 集群:
| 节点角色 | 主机名 | IP 地址 | 初始角色 |
|---|---|---|---|
| PostgreSQL 节点 1 | pg1 | 192.168.1.20 | 主库 |
| PostgreSQL 节点 2 | pg2 | 192.168.1.21 | 从库 |
| PostgreSQL 节点 3 | pg3 | 192.168.1.22 | 从库 |
安装与配置
安装 PostgreSQL
在所有节点上安装 PostgreSQL
bash
# 在所有节点上执行
yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
yum install -y postgresql13 postgresql13-server postgresql13-contrib初始化 PostgreSQL 数据目录
bash
# 在所有节点上执行
/usr/pgsql-13/bin/postgresql-13-setup initdb配置 PostgreSQL
修改 postgresql.conf 文件
在所有节点上修改 /var/lib/pgsql/13/data/postgresql.conf 文件,根据 PostgreSQL 版本调整配置:
ini
# 基本配置
listen_addresses = '*'
port = 5432
# 复制配置
# PostgreSQL 10+ 使用 replica,PostgreSQL 13+ 建议使用 logical 以支持更多功能
wal_level = replica
hot_standby = on
max_wal_senders = 10
max_replication_slots = 10
# PostgreSQL 13+ 使用 wal_keep_size 替代 wal_keep_segments
wal_keep_size = 8192
# 连接配置
max_connections = 100
# 性能配置
shared_buffers = 256MB
work_mem = 4MB
maintenance_work_mem = 64MB修改 pg_hba.conf 文件
在所有节点上修改 /var/lib/pgsql/13/data/pg_hba.conf 文件,添加以下配置:
# 允许 repmgr 用户本地连接
local repmgr repmgr trust
# 允许 repmgr 用户远程连接
host repmgr repmgr 0.0.0.0/0 md5
# 允许复制用户远程连接
host replication replicator 0.0.0.0/0 md5
# 生产环境应限制 IP 地址,不建议使用 0.0.0.0/0
# host all all 192.168.1.0/24 md5启动 PostgreSQL 服务
bash
# 在所有节点上执行
systemctl start postgresql-13
systemctl enable postgresql-13安装 repmgr
在所有节点上安装 repmgr
bash
# 在所有节点上执行
yum install -y repmgr13配置 repmgr
创建 repmgr 配置文件
在所有节点上创建 /etc/repmgr/13/repmgr.conf 文件,根据 repmgr 版本调整配置:
ini
# 在 pg1 节点上
node_id=1
node_name='pg1'
conninfo='host=pg1 user=repmgr dbname=repmgr port=5432 connect_timeout=2'
data_directory='/var/lib/pgsql/13/data'
# 复制配置
repl_user='replicator'
repl_password='rep-pass'
pg_bindir='/usr/pgsql-13/bin'
# 故障转移配置
# 可以设置为 automatic(自动故障转移)或 manual(手动故障转移)
failover='automatic'
promote_command='/usr/pgsql-13/bin/repmgr standby promote -f /etc/repmgr/13/repmgr.conf --log-to-file'
follow_command='/usr/pgsql-13/bin/repmgr standby follow -f /etc/repmgr/13/repmgr.conf --log-to-file --upstream-node-id=%n'
# 监控配置
monitoring_history='yes'
monitor_interval_secs=2
# 日志配置
log_level='INFO'
log_file='/var/log/repmgr/repmgrd.log'注意:
- 每个节点的
node_id和node_name必须唯一 conninfo中的host应设置为节点自身的主机名或 IP 地址- 生产环境中建议使用手动故障转移,避免误判导致的数据不一致
创建 repmgr 日志目录
bash
# 在所有节点上执行
mkdir -p /var/log/repmgr
chown postgres:postgres /var/log/repmgr初始化 repmgr 集群
在主库上创建 repmgr 用户和数据库
bash
# 在 pg1 节点上执行
sudo -u postgres psql -c "CREATE ROLE repmgr WITH SUPERUSER LOGIN PASSWORD 'repmgr-pass';"
sudo -u postgres psql -c "CREATE DATABASE repmgr WITH OWNER repmgr;"
sudo -u postgres psql -c "CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'rep-pass';"初始化 repmgr 元数据库
bash
# 在 pg1 节点上执行
sudo -u postgres repmgr -f /etc/repmgr/13/repmgr.conf primary register验证主库注册
bash
# 在 pg1 节点上执行
sudo -u postgres repmgr -f /etc/repmgr/13/repmgr.conf cluster show预期输出:
ID | Name | Role | Status | Upstream | Location | Priority | Timeline | Connection string
----+------+------+--------+----------+----------+----------+----------+----------------------------------------
1 | pg1 | primary | * running | | default | 100 | 1 | host=pg1 user=repmgr dbname=repmgr port=5432 connect_timeout=2添加从库到集群
在 pg2 节点上执行基础备份
bash
# 在 pg2 节点上执行
sudo -u postgres repmgr -f /etc/repmgr/13/repmgr.conf standby clone -h pg1 -U repmgr -d repmgr --copy-external-config-files启动 pg2 节点的 PostgreSQL 服务
bash
# 在 pg2 节点上执行
systemctl start postgresql-13在 pg2 节点上注册从库
bash
# 在 pg2 节点上执行
sudo -u postgres repmgr -f /etc/repmgr/13/repmgr.conf standby register重复上述步骤添加 pg3 节点
启动 repmgrd 守护进程
创建 repmgrd 系统服务文件
在所有节点上创建 /etc/systemd/system/repmgrd-13.service 文件:
ini
[Unit]
Description=repmgrd - Replication Manager Daemon for PostgreSQL 13
After=syslog.target network.target postgresql-13.service
[Service]
Type=forking
User=postgres
Group=postgres
PIDFile=/var/run/repmgrd-13.pid
ExecStart=/usr/pgsql-13/bin/repmgrd -f /etc/repmgr/13/repmgr.conf --pid-file /var/run/repmgrd-13.pid
KillMode=process
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target启动 repmgrd 服务
bash
# 在所有节点上执行
systemctl daemon-reload
systemctl start repmgrd-13
systemctl enable repmgrd-13验证 repmgr 集群状态
查看集群状态
bash
# 在任意节点上执行
sudo -u postgres repmgr -f /etc/repmgr/13/repmgr.conf cluster show预期输出:
ID | Name | Role | Status | Upstream | Location | Priority | Timeline | Connection string
----+------+------+--------+----------+----------+----------+----------+----------------------------------------
1 | pg1 | primary | * running | | default | 100 | 1 | host=pg1 user=repmgr dbname=repmgr port=5432 connect_timeout=2
2 | pg2 | standby | running | pg1 | default | 100 | 1 | host=pg2 user=repmgr dbname=repmgr port=5432 connect_timeout=2
3 | pg3 | standby | running | pg1 | default | 100 | 1 | host=pg3 user=repmgr dbname=repmgr port=5432 connect_timeout=2查看节点详情
bash
# 在任意节点上执行
sudo -u postgres repmgr -f /etc/repmgr/13/repmgr.conf node show查看复制状态
bash
# 在任意节点上执行
sudo -u postgres repmgr -f /etc/repmgr/13/repmgr.conf replication status测试故障转移
模拟主库故障
bash
# 在 pg1 节点上执行
systemctl stop postgresql-13查看故障转移过程
bash
# 在 pg2 节点上执行
tail -f /var/log/repmgr/repmgrd.logrepmgrd 应该会检测到 pg1 节点故障,并将 pg2 或 pg3 提升为主库。
查看故障转移后的集群状态
bash
# 在任意节点上执行
sudo -u postgres repmgr -f /etc/repmgr/13/repmgr.conf cluster show预期输出显示其中一个从库已经被提升为主库,例如:
ID | Name | Role | Status | Upstream | Location | Priority | Timeline | Connection string
----+------+------+--------+----------+----------+----------+----------+----------------------------------------
1 | pg1 | primary | - failed | | default | 100 | 1 | host=pg1 user=repmgr dbname=repmgr port=5432 connect_timeout=2
2 | pg2 | primary | * running | | default | 100 | 2 | host=pg2 user=repmgr dbname=repmgr port=5432 connect_timeout=2
3 | pg3 | standby | running | pg2 | default | 100 | 2 | host=pg3 user=repmgr dbname=repmgr port=5432 connect_timeout=2恢复故障节点
修复 pg1 节点的 PostgreSQL 服务
bash
# 在 pg1 节点上执行
systemctl start postgresql-13重新注册 pg1 节点为从库
bash
# 在 pg1 节点上执行
sudo -u postgres repmgr -f /etc/repmgr/13/repmgr.conf standby follow -W查看恢复后的集群状态
bash
# 在任意节点上执行
sudo -u postgres repmgr -f /etc/repmgr/13/repmgr.conf cluster showpg1 节点应该已经作为从库重新加入集群。
repmgr 高级配置
配置级联复制
repmgr 支持级联复制,可以将从库配置为从另一个从库复制数据,减轻主库的复制压力:
bash
# 在 pg3 节点上执行,从 pg2 复制数据
sudo -u postgres repmgr -f /etc/repmgr/13/repmgr.conf standby clone -h pg2 -U repmgr -d repmgr --copy-external-config-files配置节点优先级
可以为节点设置不同的优先级,影响故障转移时的主库选举,数值越大优先级越高:
ini
# 在 repmgr.conf 中配置
priority=100 # 主库建议设置较高优先级,从库设置较低优先级配置自动故障转移延迟
可以配置故障转移延迟,避免因短暂网络波动导致误判:
ini
# 在 repmgr.conf 中配置
connection_check_type='ping' # 连接检查类型
connection_check_timeout=5 # 连接检查超时时间(秒)
reconnect_attempts=3 # 重连尝试次数
reconnect_interval=5 # 重连间隔时间(秒)
failover_timeout=60 # 故障转移超时时间(秒)配置监控
repmgr 提供了多种监控方式,便于运维人员实时了解集群状态:
使用 repmgr CLI 生成状态报告
bash
sudo -u postgres repmgr -f /etc/repmgr/13/repmgr.conf cluster show --verbose
sudo -u postgres repmgr -f /etc/repmgr/13/repmgr.conf node status监控 repmgrd 日志
bash
# 实时查看日志
tail -f /var/log/repmgr/repmgrd.log
# 搜索错误日志
grep -i error /var/log/repmgr/repmgrd.log集成 Prometheus
repmgr 可以通过 repmgr_exporter 提供 Prometheus 指标,便于集成到监控系统:
bash
git clone https://github.com/ClusterLabs/repmgr_exporter.git
cd repmgr_exporter
go build
sudo ./repmgr_exporter --web.listen-address=:9625 --repmgr.config-file=/etc/repmgr/13/repmgr.confrepmgr 最佳实践
部署建议
- 节点数量:建议部署奇数个节点(3、5 等),避免脑裂
- 硬件配置:主从节点硬件配置尽量一致,避免性能瓶颈
- 网络配置:使用高速、低延迟的网络连接,尤其是主从节点之间
- 存储配置:使用可靠的存储设备,如 RAID 10 或分布式存储
- 操作系统:所有节点使用相同的操作系统版本和配置
监控与告警
- 监控关键指标:复制延迟、节点状态、连接数、资源使用率等
- 设置合理的告警阈值:根据业务需求设置合适的告警阈值
- 监控 repmgrd 日志:及时发现和处理问题
- 定期生成状态报告:分析集群状态,提前发现潜在问题
- 集成监控系统:将 repmgr 监控指标集成到现有的监控系统中
备份策略
- 定期全量备份:使用 pg_basebackup 或第三方工具进行定期全量备份
- 连续 WAL 归档:配置 WAL 归档到可靠的存储设备,确保可以进行 PITR 恢复
- 测试恢复流程:定期测试从备份恢复的流程,确保备份可用
- 备份多个节点:考虑在多个节点上进行备份,提高备份的可靠性
故障转移测试
- 定期演练:定期进行故障转移演练,验证故障转移流程的正确性
- 测试场景:主库崩溃、网络故障、存储故障等
- 记录演练结果:分析演练中发现的问题,持续改进
- 制定回滚计划:故障转移后如果出现问题,要有明确的回滚计划
安全配置
- 使用强密码:为 repmgr 和复制用户设置强密码,定期更换
- 配置适当的 pg_hba.conf:限制访问 IP 地址和用户,不建议使用 0.0.0.0/0
- 启用 SSL/TLS:加密数据库连接,保护数据传输安全
- 保护 repmgr 配置文件:修改配置文件权限,避免泄露敏感信息
- 定期更新系统和软件:及时安装安全补丁,避免已知漏洞
版本升级
- 测试升级:在测试环境中验证升级过程,确保升级不会导致问题
- 备份数据:升级前进行全量备份,以便在升级失败时恢复
- 顺序升级:先升级 repmgr,再升级 PostgreSQL
- 监控升级过程:密切监控升级过程,及时处理出现的问题
常见问题与解决方案
从库无法连接到主库
问题:从库无法连接到主库进行复制
解决方案:
- 检查网络连接,确保节点之间可以相互通信
- 检查 pg_hba.conf 配置,确保允许复制用户从从库 IP 地址连接
- 检查复制用户的密码是否正确
- 检查主库的 max_wal_senders 和 max_replication_slots 参数是否足够
- 检查主库的 wal_level 是否设置正确
故障转移失败
问题:主库故障后,repmgr 无法进行故障转移
解决方案:
- 检查 repmgrd 服务是否正在运行
- 检查故障转移配置是否正确,特别是 promote_command 和 follow_command
- 查看 repmgrd 日志,分析具体错误原因
- 确保有足够的从库处于正常状态
- 检查节点优先级配置,确保有合适的节点可以被提升为主库
复制延迟过高
问题:从库复制延迟过高,影响业务使用
解决方案:
- 检查主库的写入负载,是否过于集中,考虑优化查询或分库分表
- 检查网络连接,是否存在网络瓶颈,考虑使用更高带宽的网络
- 调整 wal_keep_size 参数,确保有足够的 WAL 日志供从库复制
- 考虑使用更快的存储设备,如 NVMe SSD,提高 I/O 性能
- 检查从库的资源使用率,是否存在 CPU 或内存瓶颈
- 对于级联复制,考虑调整复制拓扑,减少级联层级
节点状态显示为 "failed"
问题:节点状态显示为 "failed",无法正常参与集群
解决方案:
- 检查该节点的 PostgreSQL 服务是否正在运行
- 检查网络连接,确保可以连接到该节点
- 查看 repmgrd 日志,分析具体错误原因
- 使用
repmgr node rejoin命令将节点重新加入集群 - 如果无法重新加入,考虑重新克隆节点
版本差异说明
PostgreSQL 版本差异
| PostgreSQL 版本 | 差异说明 |
|---|---|
| 10 | 支持基本的流式复制,repmgr 5.x 支持 |
| 11 | 增强了复制功能,支持并行查询,repmgr 5.x/6.x 支持 |
| 12 | 改进了分区表功能,支持默认分区,repmgr 5.x/6.x 支持 |
| 13 | 引入并行 WAL 写入,优化了复制性能,repmgr 5.x/6.x 支持 |
| 14 | 改进了从库的 I/O 性能,repmgr 6.x 支持 |
| 15 | 增强了逻辑复制功能,repmgr 6.x 支持 |
repmgr 版本差异
| repmgr 版本 | 差异说明 |
|---|---|
| 5.x | 支持 PostgreSQL 10+,提供基本的复制管理和故障转移功能 |
| 6.x | 支持 PostgreSQL 11+,增强了监控功能,改进了故障转移算法 |
总结
基于 repmgr 的 PostgreSQL 高可用方案是一个简单易用、功能强大的解决方案,它提供了自动故障检测、手动/自动故障转移、复制管理和集群监控等功能。repmgr 架构简单,依赖少,学习曲线平缓,适合中小型 PostgreSQL 集群。
在实际部署中,需要注意以下几点:
- 确保所有节点的 PostgreSQL 配置正确,特别是复制相关的参数
- 合理配置 repmgr 的故障转移参数,根据业务需求选择自动或手动故障转移
- 配置适当的监控和告警,及时发现和处理问题
- 定期进行故障转移演练,验证故障转移流程的正确性
- 制定合理的备份策略,确保数据安全
- 关注 PostgreSQL 和 repmgr 的版本差异,选择适合的版本组合
通过遵循这些最佳实践,可以构建一个稳定、可靠的 PostgreSQL 高可用集群,满足业务的高可用性需求。
