repmgr部署主从

repmgr部署主从

环境说明

  • 数据库版本: postgresql-16.6
  • repmgr版本:repmgr-5.5.0
  • 主机:centos 7.9
编号 ip 角色 repmgr实例名
1 192.168.201.51 主节点 master
2 192.168.201.51 从节点 slave1
3 -- witness节点 witness

repmgr架构说明:
repmgr架构

部署流程

所有节点安装postgres实例

详情请查看二进制安装部分
安装完成之后需要做如下配置

  • 节点1配置文件修改:
  • 注意:节点2不需要初始化(也可以初始化)

配置postgresql.conf

mkdir /data/postgresql/log
chown -R postgres:postgres /data/postgresql/log

cd /data/postgresql/pgdata
vi postgresql.conf

listen_addresses = '*'
max_wal_senders = 10                   -- 最大允许的WAL发送进程数(大于备库数量)
max_replication_slots = 10             -- 复制槽数量
wal_level = replica                    -- 至少设置为replica(支持流式复制),生产可设为logical(支持逻辑复制)
hot_standby = on                       -- 开启热备(备库需继承该配置)
wal_log_hints = on
full_page_writes=on
shared_preload_libraries = 'repmgr'
#wal_keep_segments=100
archive_mode = on                     -- 开启WAL归档
archive_command = 'test ! -f /data/postgresql/archive/%f && cp %p /data/postgresql/archive/%f'  -- 归档命令(生产建议归档到对象存储)
wal_keep_size = 1GB                   -- 主库保留的WAL大小(防止备库同步中断 
注解:
%p 表示xlog文件名$PGDATA的相对路径,如pg_xlog/00000001000000190000007D
%f 表示xlog文件名,如00000001000000190000007D
wal_level:指定生成wal日志的级别,值为minmal,archive,hot_standby。
minmal一般的配置,archive会生成wal归档需要的日志记录,hot_standby添加备库时需要设置。

postgresql.conf参数设置
wal日志配置:
wal_level=replica

  • wal_level中有三个主要的参数:minimal, replica, orlogical,
  • minimal --不能通过基础备份和wal日志恢复数据库。
  • replica --该级别支持wal归档和复制。(=9.6版本以前的archive和hot_standby)
  • logical --在replica级别的基础上添加了支持逻辑解码所需的信息。

归档模式配置
archive_mode = on

repmgr加载
shared_preload_libraries = 'repmgr'

配置pg_hba.conf

cd /app/pgsql/data
vi pg_hba.conf
 
# "local" is for Unix domain socket connections only
local   all           all                                     trust
# IPv4 local connections:
host       all        all             127.0.0.1/32            trust
local   repmgr     repmgr                                     trust
host    repmgr     repmgr             127.0.0.1/32            trust
host    repmgr     repmgr             192.168.201.0/24        trust
host       all        all             0.0.0.0/0               md5
# IPv6 local connections:
host       all        all             ::1/128                 trust
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     trust
host    replication     all             127.0.0.1/32            trust
host    replication     all             ::1/128                 trust
 
local   replication     repmgr                                     trust
host    replication     repmgr             127.0.0.1/32            trust
host    replication     repmgr             192.168.201.0/24        trust

重启服务

pg_ctl stop -D /data/postgresql/pgdata
pg_ctl start -D /data/postgresql/pgdata -l logfile
pg_ctl reload -D /data/postgresql/pgdata

--slave节点关闭实例

pg_ctl stop -D /data/postgresql/pgdata

repmgr源码编译安装(在postgresql账户下安装)

-------------依赖安装:-------------
# CentOS 8/Alma/Rocky
sudo dnf install libcurl-devel json-c-devel

# CentOS 7
sudo yum install libcurl-devel json-c-devel

-------------插件安装:-------------
 # tar -xzvf repmgr-5.5.0.tar.gz
chown -R postgres:postgres repmgr-5.5.0
cd /opt/repmgr-5.5.0/

whereis pg_config
 pg_config:/data/postgresql/pg16/bin/pg_config

./configure --prefix=/data/postgresql/pg16
make && make install
chown -R postgres:postgres /data/postgresql/pg16

注意:
1,编译后会在/data/postgresql/pg16/bin路径下生成repmgrd和repmgr两个文件


查看版本
 /data/postgresql/pg16/bin/repmgr --version

repmgr参数文件配置

master 节点

vi /data/postgresql/repmgr.conf
 
#repmgr基本配置信息
node_id=1
node_name='master'
conninfo='host=192.168.201.51 user=repmgr dbname=repmgr password=repmgr#123 port=5432 connect_timeout=2'
data_directory='/data/postgresql/pgdata'
 
#repmgr日志配置
log_level=INFO                          
log_facility=STDERR                     
log_file='/data/postgresql/log/repmgr.log'
log_status_interval=10
 
#可执行文件配置
pg_bindir='/data/postgresql/pg16/bin/'
 
#集群faibver设置
failover='automatic'
promote_command='/data/postgresql/pg16/bin/repmgr standby promote -f /data/postgresql/repmgr.conf --log-to-file'
follow_command='/data/postgresql/pg16/bin/repmgr standby follow -f /data/postgresql/repmgr.conf --log-to-file --upstream-node-id=%n'
log_file='/data/postgresql/log/repmgr.log'

slave1 节点

vi /data/postgresql/repmgr.conf
 
#repmgr基本配置信息
node_id=2
node_name='slave1'
conninfo='host=192.168.201.65 user=repmgr dbname=repmgr password=repmgr#123 port=5432 connect_timeout=2'
data_directory='/data/postgresql/pgdata'
 
#repmgr日志配置
log_level=INFO                          
log_facility=STDERR                     
log_file='/data/postgresql/log/repmgr.log'
log_status_interval=10
 
#可执行文件配置
pg_bindir='/data/postgresql/pg16/bin'
 
#集群faibver设置
failover='automatic'
promote_command='/data/postgresql/pg16/bin/repmgr standby promote -f /data/postgresql/repmgr.conf --log-to-file'
follow_command='/data/postgresql/pg16/bin/repmgr standby follow -f /data/postgresql/repmgr.conf --log-to-file --upstream-node-id=%n'

repmgr 集群构建

-- master 节点加入集群

在主库上,创建数据库repmgr 和相关的账户 repmgr

-- master 节点配置数据库环境

  • 1.创建repmgr数据库及用户
create database repmgr;
create user repmgr with password 'repmgr#123' superuser login;
alter database repmgr owner to repmgr;

postgres=# \l
                                 List of databases
  Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges  
-----------+----------+----------+-------------+-------------+-----------------------
postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
repmgr    | repmgr   | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
          |          |          |             |             | postgres=CTc/postgres
template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
          |          |          |             |             | postgres=CTc/postgres
(4 rows)
  • 2.编辑密码文件(主从都要配置)
su - postgres
vim ~/.pgpass
192.168.201.65:5432:repmgr:repmgr:repmgr#123
192.168.201.65:5432:repmgr:repmgr:repmgr#123
chmod 0600 ~/.pgpass

对密码文件重新授权,一定一定一定要授权,否则后续节点注册的时候会提示connection to server at "192.168.152.100", port 9000 failed: fe_sendauth: no password supplied
chmod 0600 ~/.pgpass
  • 3.master节点,将master数据库注册至集群,并查看状态
su - postgres -c "/data/postgresql/pg16/bin/repmgr -f /data/postgresql/repmgr.conf primary register"
su - postgres -c "/data/postgresql/pg16/bin/repmgr -f /data/postgresql/repmgr.conf cluster show"

-- 4.slave1 节点加入集群

-- slave1节点,测试连通性并克隆master数据库数据
su - postgres -c "/data/postgresql/pg16/bin/repmgr -h 192.168.201.51 -U repmgr -d repmgr -f /data/postgresql/repmgr.conf standby clone --dry-run"

出现以下信息表示检测通过:
INFO: all prerequisites for "standby clone" are met

-- 克隆数据
su - postgres -c "/data/postgresql/pg16/bin/repmgr -h 192.168.201.51 -U repmgr -d repmgr -f /data/postgresql/repmgr.conf standby clone -F"
注意:如果有用户自己创建的表空间,需要将对应的目录创建

-- 启动slave1节点数据库
su - postgres

pg_ctl stop -D /data/postgresql/pgdata
pg_ctl start -D /data/postgresql/pgdata -l logfile
pg_ctl reload -D /data/postgresql/pgdata


pg_ctl start -l $PGLOG
-- slave1节点,将slave1数据库注册到集群,并查看状态
su - postgres -c "/data/postgresql/pg16/bin/repmgr -f /data/postgresql/repmgr.conf standby register"
su - postgres -c "/data/postgresql/pg16/bin/repmgr -f /data/postgresql/repmgr.conf cluster show"

-- 注意:如果数据量很大,则在搭建从库时需要加上--fast-checkpoint参数,否则调用pg_basebackup备份的过程会非常慢。

自此,repmgr的主从就搭建好了,如果还需要添加witness节点,可以使用以下命令添加:
查看已注册的节点信息和复制状态:

任何一个节点上:检查集群节点信息
select * from repmgr.repmgr.nodes;
主节点上:检查主从复制状态
select * from pg_stat_replication ;

如果还有其他节点要加入:

slave2 节点加入集群
--slave2节点,测试连通性并克隆master数据库数据
su - postgres -c "/data/postgresql/pg16/bin/repmgr -h 192.168.201.51 -U repmgr -d repmgr -f /data/postgresql/repmgr.conf standby clone --dry-run"
rm -rf /data/postgresql/pgdata/*
su - postgres -c "/data/postgresql/pg16/bin/repmgr -h 192.168.201.51 -U repmgr -d repmgr -f /data/postgresql/repmgr.conf standby clone -F"
--启动slave2节点数据库
su - postgres
pg_ctl start -l $PGLOG
--slave2节点,将slave2数据库注册到集群,并查看状态
su - postgres -c "/data/postgresql/pg16/bin/repmgr -f /data/postgresql/repmgr.conf standby register"
su - postgres -c "/data/postgresql/pg16/bin/repmgr -f /data/postgresql/repmgr.conf cluster show"

-- 注意:如果数据量很大,则在搭建从库时需要加上--fast-checkpoint参数,否则调用pg_basebackup备份的过程会非常慢。
添加witness 节点

注意:witness节点准备工作和slave节点基本一致,只是不需要克隆数据

repmgr配置文件

#repmgr基本配置信息
node_id=3
node_name='witness'
conninfo='host=192.168.201.51 user=repmgr dbname=repmgr password=repmgr port=5432 connect_timeout=100'
data_directory='/data/postgresql/pgdata'

#repmgr日志配置
log_level=INFO                          
log_facility=STDERR                     
log_file='/data/postgresql/log/repmgr.log'
log_status_interval=10

#可执行文件配置
pg_bindir='/data/postgresql/pg16/bin/'


#集群faibver设置
failover='automatic'
promote_command='/data/postgresql/pg16/bin/repmgr standby promote -f /data/postgresql/repmgr.conf --log-to-file'
follow_command='/data/postgresql/pg16/bin/repmgr standby follow -f /data/postgresql/repmgr.conf --log-to-file --upstream-node-id=%n'
log_file='/data/postgresql/log/repmgr.log'

repmgr注册

repmgr -h 192.168.152.100 -U repmgr -d repmgr -p9000 -f /usr/local/pgsql16/repmgr/repmgr.conf witness register

开启repmgrd守护进程

--开启守护进程(故障自动转移)

su - postgres -c "/data/postgresql/pg16/bin/repmgrd -f /data/postgresql/repmgr.conf -d  -p /tmp/repmgrd.pid"

--停止守护进程

REPMGRD_PID=`ps -ef | grep repmgrd|grep   -v grep |awk '{print  $2}'`
kill -9 $REPMGRD_PID

其他 repmgr 管理命令

repmgr primary register 安装pg的repmgr扩展并注册为主节点

repmgr primary unregister 注销不活动的主节点

repmgr standby clone 从其他节点复制数据到从节点

repmgr standby register 注册从节点(添加从的信息到repmgr元数据)

repmgr standby unregister repmgr元数据中移除从的信息

repmgr standby promote 将从提升为主

repmgr standby follow 将从跟随新主

repmgr standby switchover 将从提升为主并将主降级为从

repmgr witness register 注册一个观察节点

repmgr witness unregister 移除一个观察节点

repmgr node status 显示节点的基本信息和复制状态

repmgr node check 从复制的角度对节点进行健康监测

repmgr node rejoin 重新加入一个失效节点到集群

repmgr cluster show 显示所有集群中注册的节点信息

repmgr cluster matrix 在所有节点运行show并汇总

repmgr cluster crosscheck 在节点间两两交叉监测连接

repmgr cluster event 输出时间记录

repmgr cluster cleanup 清理监控历史

主备切换并查看

注意:切换之前需要配置postgres用户的互信
使用 repmgr 部署的 PostgreSQL 主备集群,常见的主备切换方案分为手动切换和自动切换两大类,具体如下:

✅ 一、手动主备切换(Switchover)

适用于计划内维护,如主库升级、硬件更换等场景。
切换流程:

- 原主库被干净关闭(pg_ctl stop)。
- 指定备库被提升为主库(pg_promote())。
- 原主库以新备库身份重新加入集群,需执行:

案例

1.预览切换(备库上执行:)

su - postgres -c "/data/postgresql/pg16/bin/repmgr -f /data/postgresql/repmgr.conf standby switchover --siblings-follow -U repmgr --dry-run --verbose"

2.正式执行

su - postgres -c "/data/postgresql/pg16/bin/repmgr -f /data/postgresql/repmgr.conf standby switchover --siblings-follow -U repmgr --verbose"
su - postgres -c "/data/postgresql/pg16/bin/repmgr -f /data/postgresql/repmgr.conf cluster show"

--dry-run:模拟切换,检查条件是否满足。
--siblings-follow:切换后让其他备库自动指向新主库。

3.切换完成之后,需要先停止原来的主库让新的备库追WAL日志
--故障节点修复后,重新加入集群(原主节点down了之后,启动以后standby节点切换成了主节点,这时,原来的primay节点需要通过rewind命令恢复增量数据,拉回集群,如果需要,还可以做主从切换,将primry切换回主节点)
先停止

pg_ctl stop -D /data/postgresql/pgdata

执行同步(在原主库上执行)
注意:这里的host=192.168.201.65  是连接的新主库
su - postgres -c "/data/postgresql/pg16/bin/repmgr node rejoin -d 'host=192.168.201.65 user=repmgr dbname=repmgr' --force-rewind --verbose -f /data/postgresql/repmgr.conf"
su - postgres -c "/data/postgresql/pg16/bin/repmgr -f /data/postgresql/repmgr.conf cluster show"

--force-rewind 会自动调用 pg_rewind,把 node1 回退到与新主库一致的时间线,再追增 WAL。
成功后 node1 以 standby 身份重新加入集群,无需再手动 pg_basebackup。

✅ 二、自动主备切换(Failover)

适用于主库宕机等突发故障场景,依赖 repmgrd 守护进程。

  1. 启用自动切换的必要条件
    所有节点启用 repmgrd 守护进程:
repmgrd start -f /path/to/repmgr.conf

配置文件中必须包含以下参数:

promote_command='/path/to/promote.sh'
follow_command='/path/to/follow.sh'
  1. 自动切换流程
- 主库故障,repmgrd 检测到连接中断。
- 根据选举规则(LSN > Priority > Node ID)自动选出新主库。
- 执行 promote_command 提升新主库。
- 其他备库执行 follow_command 指向新主库。
- 原主库恢复后,需手动重新加入集群(node rejoin)。

3.案例:
注意:只要包含了如下两个内容就能实现自动切换:
promote_command='/path/to/promote.sh'
follow_command='/path/to/follow.sh'

修改/data/postgresql/repmgr.conf:

shared_preload_libraries = 'repmgr'
monitor_interval_secs=2
connection_check_type=connection
reconnect_attempts==6
reconnect_interval=4
failover=automatic
promote_command='/data/postgresql/pg16/bin/repmgr standby promote -f /data/postgresql/repmgr.conf --log-to-file'
follow_command='/data/postgresql/pg16/bin/repmgr standby follow -f /data/postgresql/repmgr.conf --log-to-file --upstream-node-id=%n'
log_level='INFO'
log_facility='STDERR'
log_file='/tmp/repmgr.log'
log_status_interval=300
repmgrd_service_start_command = 'repmgrd --daemonize=true'
repmgrd_service_stop_command = 'kill `cat /data/postgresql/pgdata/repmgrd.pid`'
repmgrd_pid_file=' /data/postgresql/pgdata/repmgrd.pid'



eg:
#repmgr基本配置信息
node_id=2
node_name='slave1'
conninfo='host=192.168.201.65 user=repmgr dbname=repmgr password=repmgr connect_timeout=2'
data_directory='/data/postgresql/pgdata'
 
#repmgr日志配置
log_level=INFO                          
log_facility=STDERR                     
log_file='/data/postgresql/log/repmgr.log'
log_status_interval=10
 
#可执行文件配置
pg_bindir='/data/postgresql/pg16/bin'
 
#集群faibver设置
failover='automatic'
promote_command='/data/postgresql/pg16/bin/repmgr standby promote -f /data/postgresql/repmgr.conf --log-to-file'
follow_command='/data/postgresql/pg16/bin/repmgr standby follow -f /data/postgresql/repmgr.conf --log-to-file --upstream-node-id=%n'
repmgrd_service_start_command = 'repmgrd --daemonize=true -f /data/postgresql/repmgr.conf -d  -p /data/postgresql/pgdata/repmgrd.pid'
repmgrd_service_stop_command = 'kill `cat /data/postgresql/pgdata/repmgrd.pid`'
repmgrd_pid_file='/data/postgresql/pgdata/repmgrd.pid'


启动repmgr自动切换的守护进程
su - postgres -c "nohup repmgr -f /data/postgresql/repmgr.conf daemon start &"

--启动守护进程:
repmgr daemon start
repmgr daemon status

--自动failover之后需手工将原主节点恢复成备节点,然后执行repmgr-f /data/postgresql/repmgr.conf standby register --force  ,否则下次不会自动failover。

注意:自动failover之后需手工将原主节点恢复成备节点,然后执行repmgr-f /data/postgresql/repmgr.conf standby register --force ,否则下次不会自动failover

✅ 三、辅助组件建议(增强高可用)

repmgr 本身不提供 VIP 漂移或仲裁机制,建议结合以下工具:

工具 作用
Keepalived 提供虚拟 IP(VIP)漂移,客户端透明切换
HAProxy 读写分离、连接路由
Pacemaker 提供资源级高可用(如服务监控)

✅ 四、典型切换命令汇总

场景 命令示例
手动切换 repmgr standby switchover --siblings-follow
手动提升备库 repmgr standby promote
自动故障转移 依赖 repmgrd + promote_command
节点重加入 repmgr node rejoin ... --force-rewind

✅ 总结建议

场景 推荐方案
计划内维护 手动 switchover,安全可控
主库宕机 启用 repmgrd 实现自动 failover
客户端透明 配合 Keepalived + VIP 漂移
多节点集群 使用 --siblings-follow 减少手动干预

其他命令:

--从库重新跟随新主库

su - postgres -c "/data/postgresql/pg16/bin/repmgr -f /data/postgresql/repmgr.conf standby follow"
su - postgres -c "/data/postgresql/pg16/bin/repmgr -f /data/postgresql/repmgr.conf cluster show"

-驱逐备库节点(在备节点执行)

su - postgres -c "/data/postgresql/pg16/bin/repmgr standby unregister -f /data/postgresql/repmgr.conf"
 

--注销不活动的主节点

su - postgres -c "/data/postgresql/pg16/bin/repmgr primary unregister -f /data/postgresql/repmgr.conf"
 

--主节点故障时,手动升级备库为主节点

su - postgres -c "/data/postgresql/pg16/bin/repmgr standby promote -f /data/postgresql/repmgr.conf --siblings-follow"

--主节点故障,然后新恢复之后,原来的主节点就成为了standby节点,但是流的状态不会自动恢复,需要执行如下命令,让standby重新复制主库的流
在失败的节点上先关闭数据库,然后执行重新加入

pg_ctl stop
repmgr node rejoin -f /data/postgresql/repmgr.conf -d 'host=192.168.201.51 dbname=repmgr user=repmgr' --force-rewind --config-files=postgresql.conf --verbose

keepalived配置

keepalived在此架构中,只作为提供VIP的工具,不进行故障转移操作,所以配置相对简单,其配置如下:

-- master节点
/etc/keepalived/keepalived.conf

global_defs {
    router_id pg_ha
# enable_script_security
}


vrrp_script checkpg {
    script "/etc/keepalived/scripts/checkpg.sh"
    interval 15
    fall 3
    rise 1
}
vrrp_instance VI_pgusdp {
    state BACKUP
    interface eth0
    virtual_router_id 152
    priority 100
    advert_int 1
    nopreempt                       
    authentication {
        auth_type PASS
        auth_pass 234235
    }
    track_script {
        checkpg
    }
    notify_master "/etc/keepalived/scripts/master.sh"
    notify_backup "/etc/keepalived/scripts/slave.sh"
    virtual_ipaddress {
        192.168.60.234/24
    }
}


-- slave1节点
/etc/keepalived/keepalived.conf

global_defs {
    router_id pg_ha
# enable_script_security
}


vrrp_script checkpg {
    script "/etc/keepalived/scripts/checkpg.sh"
    interval 15
    fall 3
    rise 1
}
vrrp_instance VI_pgusdp {
    state BACKUP
    interface eth0
    virtual_router_id 152
    priority 90
    advert_int 1
    nopreempt                       
    authentication {
        auth_type PASS
        auth_pass 234235
    }
    track_script {
        checkpg
    }
    notify_master "/etc/keepalived/scripts/master.sh"
    notify_backup "/etc/keepalived/scripts/slave.sh"
    virtual_ipaddress {
        192.168.60.234/24
    }
}

-- slave2节点
/etc/keepalived/keepalived.conf

global_defs {
    router_id pg_ha
# enable_script_security
}


vrrp_script checkpg {
    script "/etc/keepalived/scripts/checkpg.sh"
    interval 15
    fall 3
    rise 1
}
vrrp_instance VI_pgusdp {
    state BACKUP
    interface eth0
    virtual_router_id 152
    priority 80
    advert_int 1
    nopreempt                       
    authentication {
        auth_type PASS
        auth_pass 234235
    }
    track_script {
        checkpg
    }
    notify_master "/etc/keepalived/scripts/master.sh"
    notify_backup "/etc/keepalived/scripts/slave.sh"
    virtual_ipaddress {
        192.168.60.234/24
    }
}

cat > /etc/keepalived/scripts/checkpg.sh <<"EOF"

#!/bin/bash
export PGDATABASE=postgres
export PGPORT=5432
export PGUSER=postgres
export PGBIN=//data/postgresql/pg16/bin
export PGDATA=/data/pgdata
LOGFILE=/etc/keepalived/log/keepalived.log
nc -w 3 localhost 5432 </dev/null
a=`echo $?`
if [ $a -eq 1 ] ;then
exit 1
else
        SQL1='SELECT pg_is_in_recovery from pg_is_in_recovery();'
        db_role=`echo $SQL1  | ${PGBIN}/psql -d $PGDATABASE -U $PGUSER -h localhost $PGDATA -At -w`
        if [ $db_role == 't' ];then
                exit 1
        fi
fi

EOF

cat > /etc/keepalived/scripts/master.sh <<"EOF"

LOGFILE=/etc/keepalived/log/keepalived.log
export PGDATABASE=postgres
export PGPORT=5432
export PGUSER=postgres
export PGBIN=//data/postgresql/pg16/bin
export PGDATA=/data/pgdata
LOGFILE=/etc/keepalived/log/keepalived.log
SQL1='SELECT pg_is_in_recovery from pg_is_in_recovery();'
db_role=`echo $SQL1  | ${PGBIN}/psql -d $PGDATABASE -U $PGUSER -h localhost -At -w`
if [ $db_role == 't' ];then
   echo -e `date +"%F %T"` "the current database is standby DB! " >> $LOGFILE
  exit 1
else
   echo -e `date +"%F %T"` "the current database is master DB!" >> $LOGFILE
fi
EOF

cat > /etc/keepalived/scripts/slave.sh <<"EOF"

LOGFILE=/etc/keepalived/log/keepalived.log
export PGDATABASE=postgres
export PGPORT=5432
export PGUSER=postgres
export PGBIN=//data/postgresql/pg16/bin
export PGDATA=/data/pgdata
LOGFILE=/etc/keepalived/log/keepalived.log
SQL1='SELECT pg_is_in_recovery from pg_is_in_recovery();'
 db_role=`echo $SQL1  | ${PGBIN}/psql -d $PGDATABASE -U $PGUSER -h localhost $PGDATA -At -w`
 if [ $db_role == 't' ];then
   echo -e `date +"%F %T"` "the current database is standby DB! " >> $LOGFILE
else
   echo -e `date +"%F %T"` "the current database is master DB!" >> $LOGFILE
fi
EOF

chmod +x /etc/keepalived/scripts/*
systemctl start keepalived

常见报错处理

主从连接认证问题

报错信息:

connection to server at "192.168.201.65", port 5432 failed: fe_sendauth: no password supplied

根本原因是 repmgr 在连接节点 192.168.201.65(slave1)时没有提供数据库密码,而 PostgreSQL 在该节点上 要求密码认证。

  • fe_sendauth: no password supplied 表示客户端尝试连接时未提供密码。
  • user=repmgr 表示连接使用的是 repmgr 用户。
  • 连接字符串中 未包含密码,导致认证失败。

解决方案(任选其一)

方案一:在 repmgr.conf 中添加密码
修改 /data/postgresql/repmgr.conf,增加 conninfo 中的密码字段:

conninfo='host=192.168.201.65 user=repmgr dbname=repmgr password=your_password connect_timeout=2'

- 注意:密码中如有特殊字符,需用单引号包裹并转义。
- 所有节点的 repmgr.conf 中 conninfo 都应包含一致密码。

方案二:使用 .pgpass 文件(推荐)
在运行 repmgr 的系统用户(如 postgres)的 home 目录下创建或编辑 .pgpass 文件:

# ~/.pgpass
192.168.201.65:5432:repmgr:repmgr:your_password
chmod 600 ~/.pgpass

- 文件权限必须是 600,否则会被忽略。
- 适用于不想在配置文件中明文写密码的场景。

方案三:调整 PostgreSQL 认证方式(不推荐生产)
如果你确认环境安全,可以将 192.168.201.65 的 pg_hba.conf 中的认证方式改为 trust 或 peer:

# pg_hba.conf
host    repmgr    repmgr    192.168.201.0/24    trust
⚠️ 仅用于测试环境,生产环境不建议关闭密码认证。

验证修复
修复后重新执行:

repmgr -f /data/postgresql/repmgr.conf cluster show --verbose

应能看到 slave1 状态正常,不再报错。

问题原因 解决方案
repmgr 连接未提供密码 conninfo 中添加 password= 或使用 .pgpass
推荐做法 使用 .pgpass 文件,避免明文密码暴露

主从复制搭建了,但是查询状态中有?,并且复制流查询不到,如何重建主备

现象描述:
主从搭建完成之后通过以下命令查询主从状态:

[postgres@sit-installer pgdata]$ /data/postgresql/pg16/bin/repmgr -f /data/postgresql/repmgr.conf  cluster show
 ID | Name   | Role    | Status        | Upstream | Location | Priority | Timeline | Connection string                                                              
----+--------+---------+---------------+----------+----------+----------+----------+---------------------------------------------------------------------------------
 1  | master | primary | * running     |          | default  | 100      | 5        | host=192.168.201.51 user=repmgr dbname=repmgr password=repmgr connect_timeout=2
 2  | slave1 | standby | ? unreachable | ? master | default  | 100      |          | host=192.168.201.65 user=repmgr dbname=repmgr password=repmgr connect_timeout=2


或者在备库不加-F force强制主注册备库时,报以下错误:  导致注册失败
ARNING: node "slave1" not found in "pg_stat_replication"

查询复制流信息也查询不到:
select * from pg_stat_replication;

但是节点信息是能查询到的
select * from repmgr.nodes;

原因分析:
repmgr 能够连到主库,但从库 slave1 的 upstream 显示为 “? master”,且主库 pg_stat_replication 没有复制流记录 → 说明主备之间根本没有建立 物理复制槽 + 复制连接。

下面按排查顺序给出“一键恢复”步骤,90 % 的情况都是下面 3 个原因导致:

  • 1.确认从库是否真的在“拉”主库
    在 从库 节点(192.168.201.65)执行:
$ psql -h 127.0.0.1 -U repmgr -d repmgr -c "select pid, usename, application_name, client_addr, state, sync_state from pg_stat_wal_receiver;"

- 如果返回 0 行 → 从库根本没启动 walreceiver,需要重新注册或启动复制。
- 如果 state 是 starting/streaming 但主库仍看不到 → 多半是主库 pg_hba.conf 里没放行。
  • 2.在主库检查复制槽与连接
    主库 192.168.201.51 上:
SELECT slot_name, plugin, slot_type, active, restart_lsn
FROM pg_replication_slots;

- 没有 slave1 的物理槽 → 说明从库当初 clone 时没建槽,需要手动建。
- 如果槽存在但 active = f → 从库没连;看下一步 pg_hba.conf。
  • 3.检查主库 pg_hba.conf
    确保包含 从库 IP 的复制权限,例如:
host    replication     repmgr          192.168.201.65/32       md5
改完后主库 reload:
$ pg_ctl -D $PGDATA reload

快速修复流程(不重建实例)

在 从库 上执行:

# 停止复制
$ repmgr -f /data/postgresql/repmgr.conf standby stop

# 重新 clone(增量,不重写数据目录)
$ repmgr -h 192.168.201.51 -U repmgr -d repmgr -f /data/postgresql/repmgr.conf standby clone --fast-checkpoint --force

# 启动实例
$ pg_ctl -D /data/postgresql/pgdata start

# 重新注册
$ repmgr -f /data/postgresql/repmgr.conf standby register --force

验证

$ repmgr -f /data/postgresql/repmgr.conf cluster show
posted @ 2026-05-18 13:54  数据库小白(专注)  阅读(47)  评论(0)    收藏  举报