Postgresql14+Repmgr部署
PostgreSQL 主库(Primary)
↑ ↑
| |
Standby 节点 ←→ Standby 节点(全为 Streaming Replication)
+ 每个节点都运行 repmgr(管理工具)和可选 repmgrd(守护进程)
+ 一个共享的 repmgr 管理数据库用于记录集群拓扑和状态
PostgreSQL 原生支持流复制,但不内建高可用管理机制。repmgr 构建在 PostgreSQL 基础上,负责主从拓扑管理、复制配置、故障转移(failover)、主备切换(switchover)等功能。
工作机制核心组成
🔹 1. 数据库复制机制(Streaming Replication)
- PostgreSQL 提供主库 WAL 日志流式复制给 standby 节点。
- repmgr 通过 standby clone 自动搭建好复制关系。
🔹 2. 集群信息存储在 repmgr 数据库表中
- 所有节点都注册到一个共用的 PostgreSQL 数据库(一般为主库):
- 表包括 repl_nodes、repl_events 等
- 每个节点使用自己的 repmgr.conf 定义身份、连接信息、优先级等
🔹 3. 故障检测与自动切换(repmgrd 守护进程)
- 每个节点运行 repmgrd:
- 轮询主库健康状态(连接、ping、同步延迟)
- 若发现主库故障,优先级最高、距离最近的 standby 发起 promote
- 其他 standby 节点随后自动执行 follow_command 连接新的主库
⚠️ 要实现自动 failover,必须启用 repmgrd,并配置好 promote_command 与 follow_command。
🔹 4. 集群维护工具
- repmgr cluster show:查看拓扑和状态
- repmgr standby clone:克隆主库数据到 standby
- repmgr standby register:注册节点信息
- repmgr standby follow:变更 standby 的上游
- repmgr standby promote:提升为主库
- repmgr cluster switchover:有序主备切换
🔹 5. 无共享存储、无仲裁机制
- repmgr不提供仲裁(quorum),也不提供 VIP 自动漂移
- 所以通常结合 keepalived、Pacemaker、HAProxy 等组件用于漂移或路由
一、环境准备
1.1 软件版本:
postgresql 14.6
repmgr 5.3.3 下载地址:https://github.com/EnterpriseDB/repmgr/releases
centos7.9
序号 | 主机 | IP地址 | 端口 | 备注 |
1 | pgtest1 | 192.168.24.11 | 5432 | |
2 | pgtest2 | 192.168.24.12 | 5432 | |
3 | Pgtest3 | 192.168.24.13 | 5432 |
1.2 配置hosts文件
cat >>/etc/hosts<<EOF
192.168.24.11 pgtest1
192.168.24.12 pgtest2
192.168.24.13 pgtest3
EOF
1.3 同步时间
所有服务器的时区及时间需要保持同步
timedatectl set-timezone Asia/Shanghai
1.4 关闭防火墙和 selinux
systemctl stop firewalld
systemctl disable firewalld
vi /etc/selinux/config
SELINUX=disabled
二、pg数据库安装
--所有节点执行相同操作
2.1 安装依赖包
yum install -y perl-ExtUtils-Embed readline zlib-devel pam-devel libxml2-devel libxslt-devel openldap-devel python-devel gcc-c++ openssl-devel cmake gcc* readline-devel zlib bison flex bison-devel flex-devel openssl openssl-devel
2.2 创建用户和目录
- 创建用户、组
groupadd postgres
echo "postgres" | passwd --stdin postgres
- 创建目录
mkdir -p /postgresql/{pgdata,archive,pg14,soft}
chown -R postgres. /postgresql
chmod -R 700 /postgresql
2.3 配置postgres用户环境变量
su - postgres
cat >>~/.bash_profile<<EOF
export PGHOME=/postgresql/pg14
export PGDATA=/postgresql/pgdata
export PATH=$PGHOME/bin:$PATH
export LD_LIBRARY_PATH=$PGHOME/lib:$LD_LIBRARY_PATH
EOF
--立即生效
source ~/.bash_profile
2.4 上传安装介质并解压
tar zxvf postgresql-14.6.tar.gz
2.5 编译安装postgresql
./configure --prefix=/postgresql/pg14 --with-pgport=5432
make world &&make install-world
2.6 配置数据库(主库)
--初始化数据库
[postgres@pgtest1 ~]$ initdb -D $PGDATA
---修改参数
- 检查并修改postgresql.conf以下参数
listen_addresses = '*'
archive_mode = on
archive_command = 'cp %p /postgresql/arch/%f'
wal_level = replica
log_destination = 'csvlog'
logging_collector = on
hot_standby = on
wal_log_hints = on
- 修改pg_hba.conf文件,添加以下参数
host all all 0.0.0.0/0 trust
host all all 0.0.0.0/0 scram-sha-256
host replication all 0.0.0.0/0 trust
host replication all 0.0.0.0/0 scram-sha-256
本实验流复制用户使用postgres超级用户。
--启动主库。
[postgres@pgtest1 ~]$ pg_ctl -D /postgresql/pgdata -l logfile start
--设置postgres密码
[postgres@pgtest1 ~]$ psql
psql (14.6)
Type "help" for help.
postgres=# alter user postgres password 'postgres';
2.7 创建备库
--复制备库1
[postgres@pgtest2 ~]$ pg_basebackup -Fp -Pv -Xs -R -h 192.168.24.11 -p 5432 -Upostgres -D /postgresql/pgdata
--启动备库
[postgres@pgtest2 ~]$ pg_ctl start
--复制备库2
[postgres@pgtest3 ~]$ pg_basebackup -Fp -Pv -Xs -R -h 192.168.24.11 -p 5432 -Upostgres -D /postgresql/pgdata
--启动备库
[postgres@pgtest3 ~]$ pg_ctl start
2.8 查看数据库状态
--主库查看
postgres=# select * from pg_stat_replication;
[postgres@pgtest1 ~]$ ps -ajxf|grep postgres
三、3节点配置ssh互信
–-配置集群内postgres用户之间互信
---每个节点执行脚本setup_ssh_trust.ssh
#!/bin/bash
# SSH 互信目标主机名
NODES=("pgtest1" "pgtest2" "pgtest3")
# 当前主机名
HOSTNAME=$(hostname)
# 切换到 postgres 用户执行(若当前非 postgres 用户)
if [ "$(whoami)" != "postgres" ]; then
echo "请使用 postgres 用户执行此脚本。"
exit 1
fi
# 创建 .ssh 目录和 SSH 密钥(如果不存在)
SSH_DIR="$HOME/.ssh"
KEY_FILE="$SSH_DIR/id_rsa"
mkdir -p "$SSH_DIR"
chmod 700 "$SSH_DIR"
if [ ! -f "$KEY_FILE" ]; then
echo "生成 SSH 密钥对..."
ssh-keygen -t rsa -b 4096 -N "" -f "$KEY_FILE"
else
echo "SSH 密钥已存在,跳过生成。"
fi
# 遍历节点,配置 SSH 信任
for NODE in "${NODES[@]}"; do
if [ "$NODE" == "$HOSTNAME" ]; then
continue
fi
echo "将公钥复制到 $NODE..."
ssh-copy-id -i "$KEY_FILE.pub" "postgres@$NODE"
done
echo "SSH 互信配置完成!建议测试:"
for NODE in "${NODES[@]}"; do
if [ "$NODE" != "$HOSTNAME" ]; then
echo " ssh $NODE"
fi
done
chmod +x setup_ssh_trust.ssh
上述过程为配置3节点间的postgres的用户的互信。用date 检验,确保集群内节点能通过postgres用户互相访问。
ssh pgtest1 date
ssh pgtest2 date
ssh pgtest3 date
四、安装repmgr(源码安装)
--所有节点执行相同操作
4.1 上传介质并解压
repmgr-5.3.3.tar.gz
tar zxvf repmgr-5.3.3.tar.gz
4.2 编译安装
[postgres@pgtest1 soft]$ cd repmgr-5.3.3/
[postgres@pgtest1 repmgr-5.3.3]$
./configure PG_CONFIG=/postgresql/pg14/bin/pg_config
[postgres@pgtest1 repmgr-5.3.3]$ make &&make install
--查看已安装版本
[postgres@pgtest1 postgresql-14.6]$ repmgr --version
repmgr 5.3.3
4.3 主库创建repmgr数据库存储元数据
create database repmgr;
4.4 配置pg_hba(所有节点)
host all postgres 192.168.24.0/24 trust
host all all 0.0.0.0/0 scram-sha-256
host replication postgres 192.168.24.0/24 trust
host replication all 0.0.0.0/0 scram-sha-256
如上,增加红色条目。
本实验采用默认超级用户postgres,并设置trust使postgres用户可以免密访问集群节点间的数据库。
或者
如果想让postgres在此处也为密码校验,则需要将trust改为md5或者scram-sha-256并在本地创建.pgpass文件,操作如下
su - postgres
touch ~/.pgpass
chmod 0600 ~/.pgpass
echo "192.168.24.11:5432:repmgr:psotgres:postgres
192.168.24.12:5432:repmgr:psotgres:postgres
">> ~/.pgpass
使用密码校验需要注意密码的加密格式,留意pg_authid系统表和password_encryption参数。
--节点间测试是否可以免密访问数据库
[postgres@pgtest2 ~]$ psql -h 192.168.24.11 -p 5432 -Upostgres
psql (14.6)
Type "help" for help.
postgres=#
4.5 配置postgresql.conf(所有节点)
在 PostgreSQL 配置文件中启用 repmgr 扩展模块(作为 shared library 加载),此操作是启动repmgr守护进行的前提。
shared_preload_libraries = 'repmgr'
重启生效
pg_ctl restart
4.5 停库并删除数据文件(备库)
因为备库要通过repmgr同步来自主库的数据,所以要事先删除备库数据。
--停库
[postgres@pgtest2 pgdata]$ pg_ctl stop
[postgres@pgtest3 pgdata]$ pg_ctl stop
--删除数据
[postgres@pgtest2 pgdata]$ rm -rf ./*
[postgres@pgtest3 pgdata]$ rm -rf ./*
五、repmgr注册及配置
5.1 配置repmgr.conf文件
--主库配置repmgr.conf文件
[postgres@pgtest1 postgresql-14.6]$ vi /postgresql/repmgr.conf
node_id=1
node_name='pgtest1'
conninfo='host=192.168.24.11 port=5432 user=postgres dbname=repmgr'
data_directory='/postgresql/pgdata'
replication_user='postgres'
replication_type='physical'
pg_bindir='/postgresql/pg14/bin'
monitoring_history=yes
monitor_interval_secs=5
log_level='debug'
log_file='/postgresql/repmgr.log'
failover='automatic'
promote_command='repmgr standby promote'
follow_command='repmgr standby follow -W -f /postgresql/repmgr.conf'
connection_check_type=ping
reconnect_attempts=3
reconnect_interval=10
--从库1配置repmgr.conf文件
[postgres@pgtest2 ~]$ vi /postgresql/repmgr.conf
node_id=2
node_name='pgtest2'
conninfo='host=192.168.24.12 port=5432 user=postgres dbname=repmgr'
data_directory='/postgresql/pgdata'
replication_user='postgres'
replication_type='physical'
pg_bindir='/postgresql/pg14/bin'
monitoring_history=yes
monitor_interval_secs=5
log_level='debug'
log_file='/postgresql/repmgr.log'
failover='automatic'
promote_command='repmgr standby promote -f /postgresql/repmgr.conf'
follow_command='repmgr standby follow -f /postgresql/repmgr.conf -W'
connection_check_type=ping
reconnect_attempts=3
reconnect_interval=10
--从库2配置repmgr.conf文件
[postgres@pgtest3 ~]$ vi /postgresql/repmgr.conf
node_id=3
node_name='pgtest3'
conninfo='host=192.168.24.13 port=5432 user=postgres dbname=repmgr'
data_directory='/postgresql/pgdata'
replication_user='postgres'
replication_type='physical'
pg_bindir='/postgresql/pg14/bin'
monitoring_history=yes
monitor_interval_secs=5
log_level='debug'
log_file='/postgresql/repmgr.log'
failover='automatic'
promote_command='repmgr standby promote -f /postgresql/repmgr.conf'
follow_command='repmgr standby follow -f /postgresql/repmgr.conf -W'
connection_check_type=ping
reconnect_attempts=3
reconnect_interval=10
5.2 使用repmgr命令注册主库
[postgres@pgtest1 ~]$ repmgr -f /postgresql/repmgr.conf primary register --force
INFO: connecting to primary database...
DEBUG: connecting to: "user=postgres dbname=repmgr host=192.168.24.11 port=5432 connect_timeout=2 fallback_application_name=repmgr options=-csearch_path="
NOTICE: attempting to install extension "repmgr"
NOTICE: "repmgr" extension successfully installed
NOTICE: primary node record (ID: 1) registered
5.3 使用repmgr命令克隆备库(备库执行)
--备库1
--check
[postgres@pgtest2 postgresql]$ repmgr -h 192.168.24.11 -p5432 -Upostgres -drepmgr -f /postgresql/repmgr.conf standby clone --dry-run
--clone
[postgres@pgtest2 pgdata]$ repmgr -h 192.168.24.11 -p5432 -Upostgres -drepmgr -f /postgresql/repmgr.conf standby clone
--启动备库
[postgres@pgtest2 pgdata]$ pg_ctl start
--备库2
--check
[postgres@pgtest3 postgresql]$ repmgr -h 192.168.24.11 -p5432 -Upostgres -drepmgr -f /postgresql/repmgr.conf standby clone --dry-run
--clone
[postgres@pgtest3 pgdata]$ repmgr -h 192.168.24.11 -p5432 -Upostgres -drepmgr -f /postgresql/repmgr.conf standby clone
--启动备库
[postgres@pgtest3 pgdata]$ pg_ctl start
5.4 查看数据库进程
--主库查看postgres进程
select * from pg_stat_replication;
[postgres@pgtest1 postgresql-14.6]$ ps -ajxf|grep postgres
5.5 使用repmgr命令注册备库
--注册备库1
[postgres@pgtest2 pgdata]$ repmgr -f /postgresql/repmgr.conf standby register --force
INFO: connecting to local node "pgtest2" (ID: 2)
DEBUG: connecting to: "user=postgres dbname=repmgr host=192.168.24.12 port=5432 connect_timeout=2 fallback_application_name=repmgr options=-csearch_path="
INFO: connecting to primary database
DEBUG: connecting to: "user=postgres dbname=repmgr host=192.168.24.11 port=5432 connect_timeout=2 fallback_application_name=repmgr options=-csearch_path="
WARNING: --upstream-node-id not supplied, assuming upstream node is primary (node ID: 1)
INFO: standby registration complete
NOTICE: standby node "pgtest2" (ID: 2) successfully registered
--注册备库2
[postgres@pgtest3 pgdata]$ repmgr -f /postgresql/repmgr.conf standby register –force
INFO: connecting to local node "pgtest3" (ID: 3)
DEBUG: connecting to: "user=postgres dbname=repmgr host=192.168.24.13 port=5432 connect_timeout=2 fallback_application_name=repmgr options=-csearch_path="
INFO: connecting to primary database
DEBUG: connecting to: "user=postgres dbname=repmgr host=192.168.24.11 port=5432 connect_timeout=2 fallback_application_name=repmgr options=-csearch_path="
WARNING: --upstream-node-id not supplied, assuming upstream node is primary (node ID: 1)
INFO: standby registration complete
NOTICE: standby node "pgtest3" (ID: 3) successfully registered
5.6 查看集群状态
--任意节点查询
[postgres@pgtest1 postgresql]$ repmgr -f /postgresql/repmgr.conf cluster show
5.7 启动repmgr守护进程
#所有节点执行
[postgres@pgtest1 ~]$ repmgrd -f /postgresql/repmgr.conf -d
[2025-05-08 12:45:21] [NOTICE] redirecting logging output to "/postgresql/repmgr.log"
[postgres@pgtest1 ~]$ ps -ef|grep repmgr
postgres 30933 30899 0 12:45 ? 00:00:00 postgres: postgres repmgr 192.168.24.13(58604) idle
postgres 30941 30899 0 12:45 ? 00:00:00 postgres: postgres repmgr 192.168.24.12(46244) idle
postgres 30962 30899 0 12:45 ? 00:00:00 postgres: postgres repmgr 192.168.24.11(40242) idle
postgres 30964 1 0 12:45 ? 00:00:00 repmgrd -f /postgresql/repmgr.conf -d
postgres 30971 22092 0 12:45 pts/1 00:00:00 grep --color=auto repmgr
[postgres@pgtest1 ~]$ vi /postgresql/pgdata/postgresql.conf
六、集群切换
注意:切换前要查看各节点同步状态,保证LSN唯一且相同,否则切换会失败并导致主库宕机。
select * from pg_stat_replication;
6.1 停用repmgrd、手动switchover(3次)
6.1.1 pgtest2节点手动切换
[postgres@pgtest2 log]$ repmgr -f /postgresql/repmgr.conf standby switchover --siblings-follow
参数说明
- -f: 指定配置文件路径(必须)
- switchover: 平滑切换命令
- --siblings-follow: 让所有其他备库自动跟随新的主节点(非常推荐)
---查看集群状态
[postgres@pgtest2 pgdata]$ repmgr -f /postgresql/repmgr.conf cluster show
6.2 pgtest3节点手动切换
[postgres@pgtest3 ~]$ repmgr -f /postgresql/repmgr.conf standby switchover --siblings-follow
---查看集群状态
[postgres@pgtest3 ~]$ repmgr -f /postgresql/repmgr.conf cluster show
6.3 pgtest1节点手动切换
[postgres@pgtest1 ~]$ repmgr -f /postgresql/repmgr.conf standby switchover --siblings-follow
---查看集群状态
[postgres@pgtest1 ~]$ repmgr -f /postgresql/repmgr.conf cluster show
6.2 停止主库服务(最常用)
#实现自动failover,必须启用 repmgrd守护进程
关闭前集群状态
--主库关闭
[postgres@pgtest1 ~]$ pg_ctl stop
waiting for server to shut down.... done
server stopped
--任意节点查看集群状态
[postgres@pgtest2 log]$ repmgr -f /postgresql/repmgr.conf cluster show
等待数秒后,发现pgtest2 standby节点自动升主。
当停止主库服务后,repmgr 成功在某个 standby 节点执行了自动 promote 升主。此时,原主库重启后仍处于“孤立”状态,不会自动加入集群,也不能直接变回 standby。要恢复集群正常状态,需要手动进行“rejoin”(重新加入集群)操作。
--重新将原主库加入集群
#关闭原主库
pg_ctl stop
#清空原主库数据目录
[postgres@pgtest1 pgdata]$ rm -rf ./*
#使用新主库克隆数据
[postgres@pgtest1 pgdata]$ repmgr -h 192.168.24.12 -p5432 -Upostgres -drepmgr -f /postgresql/repmgr.conf standby clone
#启动原主库
pg_ctl start
#注册该节点为standby节点
[postgres@pgtest1 pgdata]$ repmgr -f /postgresql/repmgr.conf standby register
#明确跟随当前主库,否则其upstream为空
[postgres@pgtest1 pgdata]$ repmgr -f /postgresql/repmgr.conf standby follow
#任意节点查看集群状态
[postgres@pgtest1 pgdata]$ repmgr -f /postgresql/repmgr.conf cluster show