【一文搞懂PGSQL】7. PostgreSQL + repmgr + witness 高可用架构

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 该文档介绍了如何构建基于PostgreSQL的高可用架构,利用repmgr进行集群管理和故障转移,并引入witness节点增强网络故障检测能力。repmgr是一款轻量级的开源工具,支持一键部署、自动故障转移及分布式节点管理。文档详细描述了环境搭建步骤,包括配置postgresql参数、安装与配置repmgr、注册集群节点以及配置witness节点等。此外,还提供了故障手动与自动切换的方法及常用命令,确保集群稳定运行。

7. PostgreSQL + repmgr + witness 高可用架构

简介

repmgr是一套开源的PostgreSQL集群管理工具,具有非常轻量级的使用特性。具体表现有以下特点:

  • 配置操作简单,可一键式完成相关部署操作;
  • 支持Auto Failover和Manual Switchover;
  • 分布式管理集群节点,易扩展,可在线增删集群节点。
  • witness节点是处理集群主库和备库之间可能存在网络拥塞、延迟、路由等问题影响,导致主库还在正常工作,而备库无法联系主库的场景。
  • 通过设置witness节点可以针对主库与备库之间切换的检查完整性,即辅助备节点监控程序实施主节点网络可见性检查,避免因网络问题导致的脑裂现象。

环境准备

节点 角色 软件
10.10.8.176 primary pg+repmgr
10.10.8.106 standby pg+repmgr
10.10.8.177 standby pg+repmgr
10.10.8.180 standby pg+repmgr

安装postgresql

安装详见标题 2 源码安装配置

https://repmgr.org

免密登录

rm -rf ~/.ssh
ssh-keygen  #一路回车

cd ~/.ssh
mv id_rsa.pub authorized_keys
scp  -r  ~/.ssh  10.10.8.176:/home/postgres/
scp  -r  ~/.ssh  10.10.8.106:/home/postgres/
scp  -r  ~/.ssh  10.10.8.177:/home/postgres/
scp  -r  ~/.ssh  10.10.8.180:/home/postgres/

ssh postgres@10.10.8.176 date
ssh postgres@10.10.8.106 date 
ssh postgres@10.10.8.177 date 
ssh postgres@10.10.8.180 date

postgresql 重点参数配置 //主库操作

cat  >/pgdata/12/data/postgresql.conf<<'EOF'
# 监听地址
listen_addresses = '0.0.0.0'
# 最大连接数
max_connections = 1000
# 缓冲区大小
shared_buffers = 2GB
# 动态共享内存类型
dynamic_shared_memory_type = posix
# 日志详细程度
wal_level = replica
# 检查点之后第一次页面更改(即使是对提示位进行非关键性的修改)写 FPI 到 WAL 中
wal_log_hints = on
# 重做日志最大物理大小
max_wal_size = 1GB
# 重做日志最小物理大小
min_wal_size = 80MB
# 开启归档
archive_mode = on
# 检查归档
archive_command = 'test ! -f /archive/%f && cp %p /archive/%f'
# 最大从库数 多设置点没事
max_wal_senders = 30
# 重做日志保存数量
wal_keep_segments = 128
# 流复制主机发送数据的超时时间
wal_sender_timeout = 60s
# 开启说明如果作为从库可以读
hot_standby = on
# 流复制的最大延迟时间
max_standby_streaming_delay = 30s
# 复制槽的最大数量(复制槽是自动检查行冲突的)
max_replication_slots = 128
# 向主库报告从库当前状态的最大时间
wal_receiver_status_interval = 10s
# 如果有错误的数据复制,是否向主库反馈
hot_standby_feedback = on
# 日志时区(prc  中华人民共和国)
log_timezone = 'PRC'
# 时间格式
datestyle = 'iso, mdy'
# 数据库时区
timezone = 'PRC'
# 系统错误消息的区域设置
lc_messages = 'C'
# 货币格式的区域设置
lc_monetary = 'C'
# 数字格式设置的区域设置
lc_numeric = 'C'
# 时间格式的区域设置
lc_time = 'C'
# 默认文本搜索配置
default_text_search_config = 'pg_catalog.english'
# 日志输出
log_destination = 'stderr'
# 开启日志采集
logging_collector = on 
# 日志路径
log_directory = '/pgdata/12/log'
# 日志格式
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
# 日志权限
log_file_mode = 0600
EOF

# 添加防火墙规则
cat  >>/pgdata/12/data/pg_hba.conf<<'EOF'
host    all             all             0.0.0.0/0               trust
host    replication     repmgr          0.0.0.0/0               trust
EOF

安装repmgr

/ 所有节点安装repmgr

# 下载包
wget  https://repmgr.org/download/repmgr-5.2.0.tar.gz

# 解压
tar xf repmgr-5.2.0.tar.gz

# 进入目录
cd repmgr-5.2.0

# 配置
./configure

# 编译
make

# 安装
make install

# 创建配置文件目录
mkdir -p  /pgdata/repmgr

# 报错 cannot create regular file ‘/usr/local/pg12/lib/postgresql/repmgr.so’: Permission denied
su - root 
chown -R postgres:postgres /usr/local/pg12

配置repmgr

配置用户 // 主库

# 创建用户
createuser -s repmgr
# 创建库
createdb repmgr -O repmgr
# 修改密码
PGPASSWORD=dyh666 psql  -c "alter user repmgr with password 'dyh666';"
# 修改查找目录
PGPASSWORD=dyh666 psql  -c "alter user repmgr set search_path to repmgr ,\"\$user\",public;"

添加配置文件 // 所有节点执行

cat  >/pgdata/repmgr/repmgr.conf<<'EOF'
# 节点ID,高可用集群各节点标识 // 每个节点不同
node_id=1
# 节点名称,高可用集群各节点名称 // 每个节点不同
node_name='pg01-182'
# 本节点数据库连接信息  // 填写本机的IP地址即可
conninfo='host=10.10.8.182  user=repmgr   dbname=repmgr connect_timeout=2'
# pg数据目录
data_directory='/pgdata/12/data'
# 流复制数据库用户,默认使用repmgr
#replication_user='replica'
# repmgr软件目录
repmgr_bindir='/usr/local/pg12/bin/'
# pg软件目录
pg_bindir='/usr/local/pg12/bin'
# 停机超时时间
#shutdown_check_timeout=10
# 日志输出
log_level=INFO
log_file='/pgdata/repmgr/repmgrd.log'
log_status_interval=10
EOF

配置数据库免密 // 所有机器配置

# 配置主备库的密码文件 .pgpass 互相通信使用 
cat >~/.pgpass<<'EOF'
10.10.8.176:5432:repmgr:repmgr:dyh666
10.10.8.106:5432:repmgr:repmgr:dyh666
10.10.8.177:5432:repmgr:repmgr:dyh666
10.10.8.180:5432:repmgr:repmgr:dyh666
EOF

# 授权 // 所以机器配置
chmod 0600 ~/.pgpass

注册完成后可以使用repmgr用户登录数据库repmgr默认库下查看生成的表来确定集群的状态

或者通过repmgr的命令查看相关的状态信息

主库加入集群

# 主库注册到集群
repmgr primary register -f /pgdata/repmgr/repmgr.conf 

# 查看集群状态
repmgr -f /pgdata/repmgr/repmgr.conf cluster show

克隆到其他节点

# 测试克隆  // 非必要操作如果你想使用现有主从做repmgr 则可以忽略
repmgr  standby clone  -h 10.10.8.183 -Urepmgr -d repmgr -f /pgdata/repmgr/repmgr.conf  --dry-run

# 正式执行   // 这里如果提示你输入密码说明你的配置有问题
repmgr  standby clone  -h 10.10.8.182 -Urepmgr -d repmgr -f /pgdata/repmgr/repmgr.conf 

# 启动pgsql
pg_ctl -D /pgdata/12/data -l logfile  start

从库加入集群

# 将 standby 节点注册到集群  --upstream-node-id=1 //指定primary 节点的ID号  
repmgr  standby register -f /pgdata/repmgr/repmgr.conf --upstream-node-id=1

# 查看集群状态
repmgr -f /pgdata/repmgr/repmgr.conf cluster show

配置 witness 节点

以上操作虽然实现了PostgreSQL的切换功能,但是需要手动去执行才能进行切换,witness 节点是监控节点,他可以监控集群的状态,当主库访问不可达或宕机时,可以通过指定的命令自动切换主库,并在代码中实现了防止脑裂的功能。

如果备节点网络上只是和witness或主节点中的一个节点不通,,则很可能存在网络中断,它不应该切换为主节点。如果备节点和witness节点相通,但和主节点不通,这证明不是网络中断,而是主节点本身不可用,因此它可以切换为主节点。

⚠️: witness节点不能在集群内,必须是独立的节点,必须为独立主库!!!

witness节点上初始化一个实例

# 清理旧实例
pg_ctl stop
rm -rf /pgdata/12/data/*
rm -rf /archive/*


# 生产初始化
initdb -A md5 -D $PGDATA -E utf8 --locale=C -W # 配置管理员密码

配置实例

cat  >/pgdata/12/data/postgresql.conf<<'EOF'
# 监听地址
listen_addresses = '0.0.0.0'
# 最大连接数
max_connections = 1000
# 缓冲区大小
shared_buffers = 2GB
# 动态共享内存类型
dynamic_shared_memory_type = posix
# 日志详细程度
wal_level = replica
# 检查点之后第一次页面更改(即使是对提示位进行非关键性的修改)写 FPI 到 WAL 中
wal_log_hints = on
# 重做日志最大物理大小
max_wal_size = 1GB
# 重做日志最小物理大小
min_wal_size = 80MB
# 开启归档
archive_mode = on
# 检查归档
archive_command = 'test ! -f /archive/%f && cp %p /archive/%f'
# 最大从库数 多设置点没事
max_wal_senders = 30
# 重做日志保存数量
wal_keep_segments = 128
# 流复制主机发送数据的超时时间
wal_sender_timeout = 60s
# 开启说明如果作为从库可以读
hot_standby = on
# 流复制的最大延迟时间
max_standby_streaming_delay = 30s
# 复制槽的最大数量(复制槽是自动检查行冲突的)
max_replication_slots = 128
# 向主库报告从库当前状态的最大时间
wal_receiver_status_interval = 10s
# 如果有错误的数据复制,是否向主库反馈
hot_standby_feedback = on
# 日志时区(prc  中华人民共和国)
log_timezone = 'PRC'
# 时间格式
datestyle = 'iso, mdy'
# 数据库时区
timezone = 'PRC'
# 系统错误消息的区域设置
lc_messages = 'C'
# 货币格式的区域设置
lc_monetary = 'C'
# 数字格式设置的区域设置
lc_numeric = 'C'
# 时间格式的区域设置
lc_time = 'C'
# 默认文本搜索配置
default_text_search_config = 'pg_catalog.english'
# 日志输出
log_destination = 'stderr'
# 开启日志采集
logging_collector = on 
# 日志路径
log_directory = '/pgdata/12/log'
# 日志格式
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
# 日志权限
log_file_mode = 0600
# 自动切换
shared_preload_libraries ='repmgr'
EOF

# 添加防火墙规则
cat  >>/pgdata/12/data/pg_hba.conf<<'EOF'
host    all             all             0.0.0.0/0               trust
host    replication     repmgr          0.0.0.0/0               trust
EOF

# 启动
 pg_ctl -D /pgdata/12/data -l logfile start

创建用户

# 创建用户
createuser -s repmgr
# 创建库
createdb repmgr -O repmgr
# 修改密码
PGPASSWORD=dyh666 psql  -c "alter user repmgr with password 'dyh666';"
# 修改查找目录
PGPASSWORD=dyh666 psql  -c "alter user repmgr set search_path to repmgr ,\"\$user\",public;"

添加 repmgr 配置

cat  >/pgdata/repmgr/repmgr.conf<<'EOF'
# 节点ID,高可用集群各节点标识 // 每个节点不同
node_id=4
# 节点名称,高可用集群各节点名称 // 每个节点不同
node_name='pg04-180'
# 本节点数据库连接信息  // 填写本机的IP地址即可
conninfo='host=10.10.8.180  user=repmgr   dbname=repmgr connect_timeout=2'
# pg数据目录
data_directory='/pgdata/12/data'
# 流复制数据库用户,默认使用repmgr
#replication_user='replica'
# repmgr软件目录
repmgr_bindir='/usr/local/pg12/bin/'
# pg软件目录
pg_bindir='/usr/local/pg12/bin'
# 停机超时时间
#shutdown_check_timeout=10
# 日志输出
log_level=INFO
log_file='/pgdata/repmgr/repmgrd.log'
log_status_interval=10
EOF

注册witness 节点到集群

# 将 witness 节点注册到集群
repmgr  witness register  -f /pgdata/repmgr/repmgr.conf  -h 10.10.8.183  --upstream-node-id=2 -Urepmgr -d repmgr

集群检查

# 集群状态拓扑
repmgr -f /pgdata/repmgr/repmgr.conf cluster show

# ssh 连接检查
repmgr -f /pgdata/repmgr/repmgr.conf cluster matrix

# repmgr连接检查
repmgr -f /pgdata/repmgr/repmgr.conf cluster crosscheck

# 显示节点基本信息和复制状态
repmgr -f /pgdata/repmgr/repmgr.conf node status

# 复制状况检查
repmgr -f /pgdata/repmgr/repmgr.conf node check

故障手动切换

主从切换的效果是将执行的命令的从库提升为主库,其他从库指向新主库,旧主库也指向新主库。

# 切换测试
repmgr -f /pgdata/repmgr/repmgr.conf standby switchover --siblings-follow  --force-rewind --dry-run

# 正式切换
repmgr -f /pgdata/repmgr/repmgr.conf standby switchover --siblings-follow  --force-rewind 

# # 集群状态拓扑
repmgr -f   /pgdata/repmgr/repmgr.conf  cluster show

可能遇见的问题:

fe_sendauth: no password supplied

一般是 pg_hba.conf 文件的防火墙权限配置的有问题

故障自动切换

pgsql 添加配置 // 所有节点

# 添加如下配置
cat >>/pgdata/12/data/postgresql.conf<<'EOF'
# 加载repmgr 
shared_preload_libraries = 'repmgr'
EOF

# 重启pg
pg_ctl  restart

repmgr配置 // 所有节点

# 配置repmgr 配置文件
vim /pgdata/repmgr/repmgr.conf
# 节点ID 唯一的
node_id=4
# 节点名 唯一的
node_name='pg-04-180'
# 本地连接信息
conninfo='host=10.10.8.180 port=5432  user=repmgr dbname=repmgr connect_timeout=2'
# pg数据目录路径
data_directory='/pgdata/12/data/'
# repmgr软件目录
repmgr_bindir='/usr/local/pg12/bin/'
# pg软件目录
pg_bindir='/usr/local/pg12/bin'
# 故障转移方法 自动
failover=automatic
# 等待提升配置
promote_command='/usr/local/pg12/bin/repmgr standby promote -f /pgdata/repmgr/repmgr.conf --log-to-file'
# 故障转移配置
follow_command='/usr/local/pg12/bin/repmgr  standby follow -f /pgdata/repmgr/repmgr.conf --log-to-file --upstream-node-id=%n'
# pg启动命令
service_start_command='pg_ctl -D /pgdata/12/data -l logfile start'
# pg关闭命令
service_stop_command='pg_ctl -D /pgdata/12/data -l logfile stop'
# pg重启命令
service_restart_command='pg_ctl -D /pgdata/12/data -l logfile restart'
# pg重载命令
service_reload_command='pg_ctl -D /pgdata/12/data -l logfile reload'
# pid文件位置
repmgrd_pid_file='/pgdata/repmgr/repmgrd.pid'
# 优先级权重
priority=100
# 日志输出
log_level=ERROR
log_file='/pgdata/repmgr/repmgrd.log'
log_status_interval=10
# 检查主库状态间隔时间
monitor_interval_secs=2
# 探测主库是否可用
connection_check_type='query'
# 尝试连接主库次数
reconnect_attempts=6
# 连接主库失败后再次连接的间隔时间
reconnect_interval=2
# repmgr 启动命令
repmgrd_service_start_command='repmgrd -f /pgdata/repmgr/repmgr.conf'
# repmgr 关闭命令
repmgrd_service_stop_command='kill -9 $(cat /pgdata/repmgr/repmgrd.pid)'
# 启动
repmgrd -f /pgdata/repmgr/repmgr.conf

# 关闭
kill -9 `cat /pgdata/repmgr/repmgrd.pid`

集群检查

# 集群状态拓扑
repmgr -f /pgdata/repmgr/repmgr.conf cluster show

# ssh 连接检查
repmgr -f /pgdata/repmgr/repmgr.conf cluster matrix

# repmgr连接检查
repmgr -f /pgdata/repmgr/repmgr.conf cluster crosscheck

# 显示节点基本信息和复制状态
repmgr -f /pgdata/repmgr/repmgr.conf node status

# 复制状况检查
repmgr -f /pgdata/repmgr/repmgr.conf node check

自动切换

# 主库执行
pg_ctl stop

# 查看集群状态
repmgr -f /pgdata/repmgr/repmgr.conf cluster show

恢复的时候执行不了的直接强制执行

但是一定要注意是什么问题,主从同步的问题就不能强制执行,执行了也报错

repmgr 常用命令

# 查看集群状态
repmgr -f /pgdata/repmgr/repmgr.conf cluster show

# primary 节点注册到集群 //主库
repmgr -f /pgdata/repmgr/repmgr.conf  primary register

# 将 standby 节点注册到集群  --upstream-node-id=1 //指定primary 节点的ID号  
repmgr standby register -f /pgdata/repmgr/repmgr.conf --upstream-node-id=1

# 强制注册一个standby 节点
repmgr  standby register    --force  -d 'host=10.10.8.176 port=5432 user=repmgr password=dyh666'


# 将 witness 节点注册到集群
repmgr -f /pgdata/repmgr/repmgr.conf  -h 10.10.8.176  --upstream-node-id=1 -Urepmgr -d repmgr witness register

# 集群删除一个standby节点
repmgr standby unregister -f /pgdata/repmgr/repmgr.conf --node-id=1

# 集群删除一个primary节点
repmgr primary unregister -f /pgdata/repmgr/repmgr.conf --node-id=1

# 集群删除 witness节点
repmgr witness  unregister -f /pgdata/repmgr/repmgr.conf   --node-id=4

# 检查切换  // 从节点执行
repmgr -f /pgdata/repmgr/repmgr.conf  standby switchover --siblings-follow --force-rewind --dry-run

# 手动切换切换  // 从节点执行
repmgr -f /pgdata/repmgr/repmgr.conf  standby switchover --siblings-follow --force-rewind

# 清理监控数据
repmgr cluster cleanup -f /pgdata/repmgr/repmgr.conf --node-id=4
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
2月前
|
SQL 监控 关系型数据库
MySQL主从复制:构建高可用架构
本文深入解析MySQL主从复制原理与实战配置,涵盖复制架构、监控管理、高可用设计及性能优化,助你构建企业级数据库高可用方案。
|
3月前
|
运维 监控 搜索推荐
MSE ZooKeeper:Flink 高可用架构的企业级选择
本文深入解析了 Apache Flink 架构中 ZooKeeper 的核心作用,包括 Leader 选举、Checkpoint 管理、作业协调及配置管理等关键功能,并结合金融风控与电商推荐等典型场景,分析了 ZooKeeper 在实际应用中的技术实现。
|
8天前
|
运维 监控 安全
公链开发中的高可用架构设计要点
本指南提供公链高可用架构的可复用流程与模板,涵盖目标拆解、先决条件、分步执行、故障排查及验收标准,结合跨链DApp与量化机器人案例,提升落地效率与系统稳定性。
|
2月前
|
存储 监控 NoSQL
Redis高可用架构全解析:从主从复制到集群方案
Redis高可用确保服务持续稳定,避免单点故障导致数据丢失或业务中断。通过主从复制实现数据冗余,哨兵模式支持自动故障转移,Cluster集群则提供分布式数据分片与水平扩展,三者层层递进,保障读写分离、容灾切换与大规模数据存储,构建高性能、高可靠的Redis架构体系。
|
2月前
|
存储 人工智能 关系型数据库
阿里云AnalyticDB for PostgreSQL 入选VLDB 2025:统一架构破局HTAP,Beam+Laser引擎赋能Data+AI融合新范式
在数据驱动与人工智能深度融合的时代,企业对数据仓库的需求早已超越“查得快”这一基础能力。面对传统数仓挑战,阿里云瑶池数据库AnalyticDB for PostgreSQL(简称ADB-PG)创新性地构建了统一架构下的Shared-Nothing与Shared-Storage双模融合体系,并自主研发Beam混合存储引擎与Laser向量化执行引擎,全面解决HTAP场景下性能、弹性、成本与实时性的矛盾。 近日,相关研究成果发表于在英国伦敦召开的数据库领域顶级会议 VLDB 2025,标志着中国自研云数仓技术再次登上国际舞台。
247 0
|
6月前
|
监控 Linux 应用服务中间件
Linux多节点多硬盘部署MinIO:分布式MinIO集群部署指南搭建高可用架构实践
通过以上步骤,已成功基于已有的 MinIO 服务,扩展为一个 MinIO 集群。该集群具有高可用性和容错性,适合生产环境使用。如果有任何问题,请检查日志或参考MinIO 官方文档。作者联系方式vx:2743642415。
1842 57
|
4月前
|
文字识别 运维 监控
架构解密|一步步打造高可用的 JOCR OCR 识别服务
本文深入解析了JOCR OCR识别服务的高可用架构设计,涵盖从用户上传、智能调度、核心识别到容错监控的完整链路,助力打造高性能、低成本的工业级OCR服务。
184 0
架构解密|一步步打造高可用的 JOCR OCR 识别服务
|
12月前
|
存储 SQL 关系型数据库
Mysql高可用架构方案
本文阐述了Mysql高可用架构方案,介绍了 主从模式,MHA模式,MMM模式,MGR模式 方案的实现方式,没有哪个方案是完美的,开发人员在选择何种方案应用到项目中也没有标准答案,合适的才是最好的。
861 3
Mysql高可用架构方案
|
7月前
|
消息中间件 存储 设计模式
RocketMQ原理—5.高可用+高并发+高性能架构
本文主要从高可用架构、高并发架构、高性能架构三个方面来介绍RocketMQ的原理。
2135 21
RocketMQ原理—5.高可用+高并发+高性能架构
|
12月前
|
运维 负载均衡 Shell
控制员工上网软件:高可用架构的构建方法
本文介绍了构建控制员工上网软件的高可用架构的方法,包括负载均衡、数据备份与恢复、故障检测与自动切换等关键机制,以确保企业网络管理系统的稳定运行。通过具体代码示例,展示了如何实现这些机制。
224 63

推荐镜像

更多
下一篇
开通oss服务