☰
PostgreSQL高可用:流复制+pgpool+pg_rman配置与故障切换实践
2026/10/2 10:23:50 网站建设 项目流程

简介:针对 PostgreSQL 数据库的高可用与读写分离需求,这份文档以流复制搭配 pgpool-II 为主线,为数据库运维及架构人员提供了一套从原理到实践的完整部署方案。内容先解析 WAL 日志在主备节点间的传输与复用机制,包括 walwriter 周期刷新、walsender 发送、walreceiver 接收以及 startup 进程应用日志的完整链路,并明确同步复制与异步复制的适用场景和选择建议;随后介绍 pgpool-II 的连接池、负载均衡、复制自动切换和连接限制功能。文档为 docx 格式,共 1 个文件,压缩包约 773KB,虽然体量不大,但正文包含版本记录与完整目录,覆盖环境准备、主库参数配置、备库初始化、pgpool 配置、启动验证与故障演练等关键环节,并含资源调整、防火墙/SELinux、时钟同步、sysctl 等基础准备条目,方便按章节直接落地。这份方案目前已有 466 人学习,适合有 PostgreSQL 基础、想快速搭建主从高可用环境的读者作为参考资料。

1. 从流复制到高可用:这份方案文档到底解决了什么问题

先给结论:PostgreSQL 自身只解决数据同步,不解决故障切换。主库宕机后,备库不会自动接管,客户端连接也不会自动转移。真正让这套架构变成“高可用”的,是 pgpool 的 watchdog 和虚拟 IP 漂移机制。而文档里的方案,本质上是把流复制、pgpool、pg_rman 三件套串成一条完整的链路——流复制保证 WAL 日志实时从主库传到备库,pgpool 负责连接池、读写分离和故障时的自动切换,pg_rman 负责离线备份兜底,覆盖误操作和恶意破坏场景。这套方案特别适合 RHEL/CentOS 下不能联网安装软件包的客户环境,文档里还专门配套了离线安装脚本。适合谁看?正在搭 PG 主备、但还没搞定 pgpool 配置的 DBA 或运维工程师,尤其是卡在 failover 不生效、虚拟 IP 不飘移这类问题上的人。

2. 环境准备与选型:先搞懂版本差异,再动手改系统参数

2.1 版本选型:3.6 和 4.1 的 pgpool 配置完全是两套写法

文档里给出了两套版本的对应关系。旧版本组合是 PostgreSQL 10.3 + pgpool-II-3.6.14,新版本组合是 PostgreSQL 12.2 + pgpool-II-4.1.1,操作系统覆盖 CentOS 6.5 和 CentOS 7.5。这里有一个容易翻车的点:pgpool 3.6 和 4.1 的配置文件格式差异很大,如果你在网上搜到的是 3.x 的配置教程,直接套到 4.x 上,启动必报错。4.x 版本把后端节点信息挪到了pgpool.conf里,但参数名和 3.x 不一样,比如 3.x 用的是backend_hostname1,4.x 虽然保留了类似写法,但增加了很多 watchdog 相关的独立配置段。我的建议是:新环境一律用新版本组合,旧版本组合只用于维护存量系统。PostgreSQL 12 和 10 在流复制上的差异主要在标识文件——10 用recovery.conf,12 改用standby.signal,这个后面专节展开。

2.2 系统参数调整:sysctl、limits、时钟同步一个都不能少

在装 PostgreSQL 之前,操作系统层有六件事要做,顺序不要乱:关闭防火墙、关闭 SELinux、配置 hosts、配置 NTP 时钟同步、调整 sysctl、调整 limit 资源限制。防火墙和 SELinux 不关,后面 pgpool 连接测试会报各种玄学错误,比如连接超时或者认证失败,但实际上根本不是密码问题。sysctl 配置里最关键的几个参数:

# /etc/sysctl.conf 追加以下内容 vm.overcommit_memory = 0 kernel.shmmax = 68719476736 kernel.shmall = 4294967296 fs.file-max = 6815744 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 net.ipv4.ip_local_port_range = 9000 65500

执行sysctl -p使配置生效。这里面kernel.shmmax和kernel.shmall决定共享内存上限,如果你的 PG 配置了shared_buffers为 2GB 以上,共享内存参数必须跟着调,否则 PG 启动直接报 "Cannot allocate memory"。ip_local_port_range影响客户端连接时的端口分配,连接数大的场景必须放开。然后是 limit 配置:

# /etc/security/limits.conf 追加 postgres soft nofile 65535 postgres hard nofile 65535 postgres soft nproc 65535 postgres hard nproc 65535

注意这里用postgres用户单独设置,不要只改全局的*,因为 PG 服务进程是以 postgres 用户运行的。nofile限制的是文件描述符数量,连接数高时不够用会报 "Too many open files",nproc限制的是进程数。还有时钟同步,主备库时间差超过一定阈值,WAL 日志的时间戳对不上,同步虽然不会中断,但排查问题时时间线混乱非常痛苦。配置好 NTP 后执行ntpdate -u 时间服务器手动校准一次,再启动chronyd或ntpd服务。

2.3 目录规划与权限:安装路径、数据目录、归档目录分开放

文档里要求创建 postgres 用户并设置密码,然后配置安装文件夹。这里有个实践中的细节:安装目录、数据目录、归档目录、备份目录最好分成四个独立的路径。

# 创建用户 useradd postgres passwd postgres # 规划目录结构 mkdir -p /opt/postgresql/pgdata # 数据目录 mkdir -p /opt/postgresql/archive # WAL 归档目录 mkdir -p /opt/postgresql/backup # pg_rman 备份目录 mkdir -p /opt/pgpool # pgpool 工作目录 # 目录权限 chown -R postgres:postgres /opt/postgresql chmod 750 /opt/postgresql/pgdata /opt/postgresql/archive

目录权限这里很多人会忽略。pgdata目录权限必须设置为 700 或 750,并且属主必须是 postgres 用户,否则 PG 初始化时直接拒绝执行。archive 目录要确保 postgres 用户有写权限,因为归档进程是在 postgres 用户下运行的。另外,不要把数据目录放在/home/postgres下,因为 home 目录的权限和挂载点可能有问题,放在/opt或/data这类独立挂载点更稳妥。

3. 安装 PostgreSQL 并配置流复制:按 12.X 版本的做法来

3.1 编译安装前的依赖准备与初始化

RHEL 环境不能联网,所以要先准备好依赖包。文档的附件里有“RHEL 安装环境获取脚本”,它的作用是在能联网的机器上先把所有依赖和 rpm 包缓存下来,再拷到客户环境离线安装。安装 PG 前必要的依赖包包括readline-devel、zlib-devel、gcc、make、flex、bison等。编译安装的流程比较固定:

# 解压源码包 tar -xzf postgresql-12.2.tar.gz cd postgresql-12.2 # 配置编译选项 ./configure --prefix=/opt/postgresql/pg12 --with-pgport=5432 # 编译安装 make -j 4 make install

--prefix指定安装路径,--with-pgport指定默认端口。如果你不指定--prefix,默认装到/usr/local/pgsql,后面环境变量和管理都要按这个路径来,所以建议从一开始就固定好安装路径。编译时间取决于机器配置,-j 4表示用 4 核并行编译。编译安装完后,PG 的可执行文件在/opt/postgresql/pg12/bin下,共享库在/opt/postgresql/pg12/lib下,这些路径后续都要配置到环境变量里。

3.2 初始化数据库与主库配置三个关键文件

初始化数据库用initdb命令,注意必须以 postgres 用户执行,而且数据目录必须为空。

# 切换到 postgres 用户 su - postgres # 设置环境变量 export PGHOME=/opt/postgresql/pg12 export PGDATA=/opt/postgresql/pgdata export PATH=$PGHOME/bin:$PATH export LD_LIBRARY_PATH=$PGHOME/lib:$LD_LIBRARY_PATH # 初始化数据目录 initdb -D $PGDATA -E UTF8 --locale=en_US.UTF-8

-E UTF8指定数据库编码,--locale指定区域。这里有个容易忽略的点:如果你用server encoding默认的SQL_ASCII,后面创建中文数据会乱码或者报错。初始化完成后,需要修改postgresql.conf和pg_hba.conf两个文件。主库上 12.X 版本的关键参数如下:

# postgresql.conf 关键参数(master 节点) listen_addresses = '0.0.0.0' port = 5432 wal_level = replica max_wal_senders = 10 wal_keep_size = 1024 hot_standby = on synchronous_commit = off synchronous_standby_names = ''

wal_level设置为replica表示启用流复制所需的 WAL 级别信息,max_wal_senders决定最多允许多少个备库连接,wal_keep_size表示保留多少 MB 的 WAL 日志在 pg_wal 目录中,防止备库追不上主库时日志被回收。hot_standby允许备库接受只读查询,这配合 pgpool 做读写分离必须开启。同步复制模式下,需要设置synchronous_standby_names为备库名非空,并且synchronous_commit = on,但异步模式更适合大多数业务,因为同步模式下主库事务提交要等备库确认,网络延迟直接变成写入延迟。

然后是pg_hba.conf,这里配置的是访问控制规则,容易踩坑的是忘了加流复制用户的规则:

# pg_hba.conf 追加 host replication replica 192.168.1.0/24 md5 host all all 192.168.1.0/24 md5

第一条是允许流复制用户从内网网段连接做 WAL 拉取,第二条是允许应用连接。注意replication这个关键字是固定写法,不是数据库名。规则顺序很重要:pg_hba.conf从上往下匹配,第一条匹配就停止,所以把精确的 replication 规则放在所有规则前面,避免被all规则抢先匹配导致权限不对。

3.3 创建流复制用户并启动主库

配置好文件后,启动主库并创建专用的复制用户,不要用超级用户 postgres 做流复制,安全性和可维护性都差。

# 启动主库 pg_ctl -D $PGDATA -l /opt/postgresql/pg12/log/pg.log start # 创建流复制用户 psql -U postgres -c "CREATE USER replica REPLICATION LOGIN PASSWORD 'replica_password';"

流复制用户需要REPLICATION权限,这个权限只能通过CREATE USER ... REPLICATION授予,普通CREATEROLE权限不够。创建完成后,在主库上执行SELECT * FROM pg_stat_replication;,此时应该空,因为备库还没连上来。

3.4 备库部署:基础备份的取法与 12.X 的标识文件

备库的搭建方式不是重新 initdb,而是从主库拉一份基础备份。常用工具是pg_basebackup,这是 PG 自带的物理备份工具,专门用于搭建流复制备库。

# 在备库执行(需要在备库上先创建好数据目录的空目录) pg_basebackup -h 192.168.1.10 -p 5432 -U replica -D /opt/postgresql/pgdata -P -R -X stream

参数说明:-h主库 IP,-U流复制用户,-D备库数据目录,-P显示进度,-R自动生成 standby 配置,-X stream表示在备份过程中使用流复制方式传输 WAL 日志。这里-R参数非常关键——它会在备库数据目录下自动生成standby.signal文件,并且在postgresql.conf末尾追加primary_conninfo配置。如果忘记加-R,备库不知道自己是备库,启动后会和主库抢数据,导致数据不一致。

12.X 版本和旧版本的核心区别就在标识文件上。旧版本(10.x 及以前)在备库数据目录下放一个recovery.conf文件,内容包含standby_mode = on和primary_conninfo,而 12.X 把这个文件取消了,改成了standby.signal空文件加postgresql.conf里的primary_conninfo参数。反过来,主库上如果是从旧版本升级过来的,需要确认recovery.done文件是否存在,12.X 版本主库不再需要这个文件。这个差异是很多从 10 升 12 的项目翻车的重灾区——旧的recovery.conf还留在数据目录里,PG 12 启动时直接报错拒绝启动。

备库启动前,还要确保postgresql.conf里配置好了primary_conninfo:

# 备库 postgresql.conf primary_conninfo = 'host=192.168.1.10 port=5432 user=replica password=replica_password application_name=standby1'

application_name必须设置,因为后面配置同步复制时,synchronous_standby_names匹配的就是这个名字。备库启动后,回到主库执行:

-- 在主库执行,查看备库是否已连接 SELECT client_addr, state, sync_state FROM pg_stat_replication;

看到state = streaming且sync_state = async,说明流复制已经建立。测试一下:在主库建一张表插入数据,在备库查询,如果数据可见(备库以只读方式运行),说明流复制链路是通的。

4. 安装配置 pgpool:从连接池到自动故障转移的完整流程

4.1 安装 pgpool 与注册数据库函数

pgpool 需要安装在两台节点上(主库节点和备库节点各一个),因为 failover 后虚拟 IP 要能从故障节点飘移到存活节点。编译安装的方式和 PG 类似:

# 解压源码包 tar -xzf pgpool-II-4.1.1.tar.gz cd pgpool-II-4.1.1 # 编译安装 ./configure --prefix=/opt/pgpool --with-pgsql=/opt/postgresql/pg12 make -j 4 make install

--with-pgsql参数指定 PG 的安装路径,因为 pgpool 需要链接 PG 的客户端库。安装完成后,还需要在 PG 中注册 pgpool 提供的函数,这些函数用于健康检查和 watchdog 状态查询。pgpool 源码包的sql目录下有针对不同 PG 版本的 SQL 脚本,需要在主库上执行:

# 以 postgres 用户,在主库执行 pgpool 的 SQL 函数 cd /opt/pgpool psql -U postgres -f /opt/pgpool/share/pgpool-II/insert_lock.sql psql -U postgres -f /opt/pgpool/share/pgpool-II/pgpool-recovery.sql psql -U postgres -f /opt/pgpool/share/pgpool-II/pgpool_adm.sql

insert_lock.sql用于解决并发插入时的锁问题,pgpool-recovery.sql提供在线恢复功能所需的函数,pgpool_adm.sql提供集群管理函数。这些脚本只需要在主库执行一次,备库通过流复制自动同步。

4.2 pgpool.conf 核心参数解析:4.X 版本的配置逻辑

pgpool 的配置文件是pgpool.conf,在/opt/pgpool/etc目录下。4.X 版本的核心配置逻辑和 3.X 差异很大,重点说 4.X 的写法。一个最小可用的集群配置包含三部分:后端节点定义、watchdog 定义、负载均衡策略。

# pgpool.conf 核心参数(节点 1) listen_addresses = '0.0.0.0' port = 9999 socket_dir = '/tmp' pcp_listen_addresses = '0.0.0.0' pcp_port = 9898 pcp_socket_dir = '/tmp' # 后端节点定义(主库和备库) backend_hostname0 = '192.168.1.10' backend_port0 = 5432 backend_weight0 = 1 backend_flag0 = 'ALWAYS_PRIMARY' backend_hostname1 = '192.168.1.11' backend_port1 = 5432 backend_weight1 = 1 backend_flag1 = 'ALLOW_TO_FAILOVER'

backend_flag0设置为ALWAYS_PRIMARY是 4.X 新增的,它告诉 pgpool 节点 0 始终是主库节点,failover 时不会把节点 0 当作备库切换目标。ALLOW_TO_FAILOVER表示允许节点 1 在节点 0 故障时被提升为主库。这个参数不配置,failover 可能不会触发自动切换。然后是负载均衡和复制模式的配置:

# 复制模式与负载均衡 replication_mode = off load_balance_mode = on master_slave_mode = on master_slave_sub_mode = 'stream' # 连接池 connection_cache = on max_pool = 4 max_init_children = 32 max_connections = 0

master_slave_mode = on表示使用流复制模式,master_slave_sub_mode = 'stream'指定流复制子类型,这个必须和 PG 的流复制方式对应。load_balance_mode = on开启读写分离,SELECT 查询会分发到两台节点,INSERT/UPDATE/DELETE 只在主库执行。connection_cache = on开启连接池,max_pool是每个子进程缓存的最大连接数,max_init_children是允许的并发连接数,这里如果设置得太小,应用并发打满后 pgpool 会把连接排队而不是拒绝,队列过长就会导致应用侧超时。

watchdog 部分是高可用的核心,4.X 配置如下:

# watchdog 配置(节点 1) use_watchdog = on wd_port = 9000 wd_hostname = '192.168.1.10' wd_interval = 5 # 虚拟 IP 配置 delegate_IP = '192.168.1.100' if_cmd_path = '/sbin' if_up_cmd = 'ip addr add $_IP_$/24 brd $_IP_$ dev eth0' if_down_cmd = 'ip addr del $_IP_$/24 dev eth0' # watchdog 对端节点 wd_lifecycle_check_port = 9694 wd_remote_0_host = '192.168.1.11' wd_remote_0_port = 9000

use_watchdog = on启用 watchdog 进程,delegate_IP是虚拟 IP,客户端连接时连这个 IP,不直接连后端节点。if_up_cmd和if_down_cmd是虚拟 IP 绑定和释放的命令,$_IP_$是 pgpool 内部变量,会自动替换成delegate_IP的地址。两个 pgpool 节点通过 watchdog 互相监控,当前持有 VIP 的节点故障后,另一个节点执行if_up_cmd把 VIP 绑到自己网卡上。这套机制里,心跳端口和虚拟 IP 的配置错误是 failover 不生效的主要原因。

4.3 pcp.conf、pool_passwd、failover 脚本的配套设置

pgpool 还有三个配置文件要一起配好:pcp.conf是 pcp 命令的认证文件,pool_passwd是数据库用户的密码文件,failover脚本是切换时执行的动作。

# 生成 pcp.conf(使用 pg_md5 生成加密密码) /opt/pgpool/bin/pg_md5 -p -u postgres # 输入密码得到 MD5 值,写入 pcp.conf echo "postgres:生成的md5值" >> /opt/pgpool/etc/pcp.conf # 生成 pool_passwd /opt/pgpool/bin/pg_md5 -m -u postgres -p 数据库密码

pg_md5 -m模式会生成pool_passwd文件,pgpool 客户端连接时用它做密码认证。如果不生成这个文件,客户端通过 pgpool 连接数据库时只能免密访问或者直接失败。然后配置 failover 脚本:

# /opt/pgpool/etc/failover.sh #!/bin/bash # 参数说明:$1 故障节点的编号,$2 故障节点的主机名,$3 故障节点的端口 # $4 被提升为主库的节点编号,$5 被提升节点的主机名,$6 被提升节点的端口 PGPOOL=/opt/pgpool/bin PGPOOL_CONF=/opt/pgpool/etc/pgpool.conf LOGDIR=/opt/pgpool/log echo "`date`: failover triggered, failed node: $1, promoted node: $4" >> $LOGDIR/failover.log # 可以在这里增加告警脚本,比如调用 zabbix 接口或发送邮件

failover 脚本的执行权限必须配置好:

chmod +x /opt/pgpool/etc/failover.sh

同时在pgpool.conf中指定:

failover_command = '/opt/pgpool/etc/failover.sh %d %h %p %D %m %M %H %P'

failover_command中%d是故障节点编号,%h是故障节点主机名,%p是故障节点端口,%D是故障节点数据目录,%m是被提升的节点编号,%M是被提升节点主机名,%H是被提升节点端口。脚本里的日志输出可以帮你确认 failover 是否真的被触发,这在排查"pgpool 没有切换"问题时是第一手证据。

4.4 启动服务并验证集群状态

两个节点配置好后,先在备库节点启动 pgpool,再启动主库节点上的 pgpool,这样可以避免备库节点抢占虚拟 IP。

# 在节点 2(备库所在节点)启动 /opt/pgpool/bin/pgpool -f /opt/pgpool/etc/pgpool.conf # 在节点 1(主库所在节点)启动 /opt/pgpool/bin/pgpool -f /opt/pgpool/etc/pgpool.conf

启动后检查状态:

# 查看 pgpool 进程 ps -ef | grep pgpool # 通过 pcp 命令查看后端节点状态 /opt/pgpool/bin/pcp_node_info -h 192.168.1.100 -p 9898 -U postgres

pcp_node_info会输出两个节点的状态,status字段应该是up或primary。如果显示down,检查 pgpool 所在节点到对应 PG 节点的网络连通性和认证配置。客户端连接测试:

# 通过 pgpool 连接数据库(虚拟 IP) psql -h 192.168.1.100 -p 9999 -U postgres -d postgres

连接成功后执行SHOW pool_nodes;,可以看到每个后端节点的状态和负载权重。如果SHOW pool_nodes能正常返回两行且状态为 up,说明 pgpool 集群已经就绪,读写分离链路已经打通。

5. 避坑指南:pgpool 部署与 эксплуатации 中五个踩过的坑

5.1 standby.signal 缺失导致备库数据被写入

现象:备库启动后,主库pg_stat_replication中看不到备库进程,但是备库日志显示 "database system is not in standby mode",最后备库也能正常接受写入。原因:12.X 版本中备库身份依赖standby.signal文件识别,如果搭建备库时用了pg_basebackup但忘记加-R参数,或者手动复制数据目录时丢了standby.signal,备库会以普通主库模式启动,两个节点同时可写,数据分叉。解决:确认备库数据目录下有standby.signal文件,没有则手动创建touch $PGDATA/standby.signal,同时检查postgresql.conf的primary_conninfo是否配置正确,然后重启备库。

5.2 pgpool 连接报 "all backend nodes are down"

现象:客户端通过 pgpool 连接数据库,报all backend nodes are down,但节点上 PG 进程实际在运行。原因:这个报错说明 pgpool 的健康检查失败,但它连接的不是 PG 的 5432 端口,而是 pgpool.conf 中配置的backend_hostname0和backend_port0。最常见的失误是backend_hostname0写成了localhost,而 pgpool 和 PG 不在同一台机器上,或者backend_port0写成了 pgpool 自己的 9999 端口。解决:用telnet测试 pgpool 所在机器到后端节点的 5432 端口是否通;检查pg_hba.conf中是否允许 pgpool 所在机器的 IP 通过认证;确认backend_hostname0填写的是真实 IP 而不是 localhost。

5.3 主库切换后回切导致两个集群分叉

现象:主库 A 故障,pgpool 自动将备库 B 提升为主库,业务恢复。后来 A 修复完成,重启 A,结果 A 和 B 都认为自己是主库,数据开始分流。原因:PG 的流复制是单向的,A 恢复后不会自动变成 B 的备库,必须手动重新搭建备库。这是很多初用者最容易忽略的坑——pgpool 只能帮你切换,不能帮你回切。解决:回切流程是先在 A 上清空数据目录,重新执行pg_basebackup从 B 拉取基础备份,配置standby.signal和primary_conninfo指向 B,让 A 以备库身份加入集群,然后再做一次 failover 把主库权切回 A。这个过程没有捷径,我也是在线上环境吃过一次亏才彻底记住。

5.4 pgpool 启动报 "could not open configuration file"

现象:启动 pgpool 时报找不到配置文件,路径确认无误但仍然报错。原因:pgpool 对配置文件路径敏感,如果使用相对路径启动,它会在当前目录查找,而 pgpool 安装进/opt/pgpool后,配置文件在/opt/pgpool/etc下,从其他目录启动自然找不到。解决:启动时强制使用绝对路径:

/opt/pgpool/bin/pgpool -f /opt/pgpool/etc/pgpool.conf -a /opt/pgpool/etc/pool_hba.conf

-a参数指定pool_hba.conf的路径,如果不指定,pgpool 默认在编译路径下找,而你如果用编译时的默认路径安装,可能和实际解压路径不一致。

5.5 虚拟 IP 漂移不生效,看日志发现 arping 失败

现象:主库节点宕机后,watchdog 状态显示切到了备库节点,但客户端访问虚拟 IP 仍然不通。原因:虚拟 IP 配置里if_up_cmd中的网卡名写错了。在 RHEL 7 上,网卡名可能是ens160而不是eth0,ip addr add命令执行失败后 VIP 根本绑不上去。解决:先确认网卡名(ip a命令查看),然后修改:

if_up_cmd = '/sbin/ip addr add $_IP_$/24 brd $_IP_$ dev ens160' if_down_cmd = '/sbin/ip addr del $_IP_$/24 dev ens160'

修改后重启 pgpool,再在主库节点手动执行ip addr add 192.168.1.100/24 dev ens160测试一遍绑定命令是否报错。这个问题的隐蔽之处在于 pgpool 日志中 watchdog 状态明明已经是STANDBY或PRIMARY,但 VIP 就是不通,排查时容易忽略 is_up_cmd 里的命令是实际在操作系统层执行的。

6. 验证与备份:用一场 Failover 测试和一套离线脚本收尾

6.1 Failover 测试的标准操作流程

配置完成不等于方案可用,故障切换必须实际演练过一次才能确认配置正确。文档的第十章给出了完整的测试路径,我强烈建议你按照这个顺序做,不要跳步。第一步,关闭主库的 PG 进程模拟数据库故障:

# 在主库节点执行,模拟 PG 进程崩溃 su - postgres -c "/opt/postgresql/pg12/bin/pg_ctl -D /opt/postgresql/pgdata stop -m immediate"

注意用immediate而不是fast,immediate模拟的是异常终止,不会做干净的关闭流程,更接近真实故障场景。执行后观察备库节点的 pgpool 日志和 failover 脚本日志,确认failover.sh被执行、备库 PG 被提升为主库。正常情况下大约 10 到 20 秒内完成切换。第二步,检查虚拟 IP 是否漂移到备库节点:

# 在备库节点执行 ip addr show | grep 192.168.1.100

如果 VIP 已经绑定在备库网卡上,说明漂移成功。第三步,通过 pgpool 连接数据库验证读写功能:

psql -h 192.168.1.100 -p 9999 -U postgres -d postgres -c "CREATE TABLE test_failover(id int);" psql -h 192.168.1.100 -p 9999 -U postgres -d postgres -c "INSERT INTO test_failover VALUES (1);"

写入如果能成功执行,说明新主库已经完全接管业务。第四步,恢复原主库节点为备库,按 5.3 的描述重新执行pg_basebackup加入集群,这时不能直接启动原主库,必须先确认它的角色是备库。整个测试做完,这套高可用方案才算真正闭环。

6.2 pg_rman 备份的初始化与验证

pg_rman 是 PostgreSQL 的备份工具,特点是不用停库,支持全量备份和归档日志备份。安装和使用有几个关键步骤。文档里特别提醒了版本问题——pg_rman 是独立于 PG 发布的,必须选择和 PG 版本匹配的版本,版本不匹配会导致备份时报 "incompatible version" 错误。初始化备份目录:

# 配置环境变量 export PATH=/opt/pg_rman/bin:$PATH export PGDATA=/opt/postgresql/pgdata export BACKUP_PATH=/opt/postgresql/backup # 创建备份目录并初始化 mkdir -p /opt/postgresql/backup pg_rman init -B /opt/postgresql/backup

-B参数指定备份目录,pg_rman init会创建备份目录结构和系统表。然后验证归档模式是否开启:

-- 查看归档状态 SHOW archive_mode; SHOW archive_command; SHOW wal_level;

archive_mode必须为on,archive_command不能为空,wal_level必须为replica或logical。如果archive_mode是off,需要在postgresql.conf中设置archive_mode = on并配置archive_command,然后重启 PG。执行全量备份:

pg_rman backup -B /opt/postgresql/backup --full -C -P

--full指定全量备份,-C压缩备份文件,-P显示进度。备份完成后执行验证:

pg_rman validate -B /opt/postgresql/backup

validate是备份流程中容易跳过的步骤,但它决定了备份能否用于恢复。validate会检查备份集完整性,确认所有 WAL 归档都可用。如果验证不通过,备份文件多点少点很难发现,真正需要恢复时就直接翻车。日常做全量备份时,我的习惯是周一全量、每天做归档备份,这样恢复点最多丢失一天的量。

6.3 离线脚本的配合用法

文档附带三个脚本:配置安装环境脚本、安装 postgreSQL 和 pg_rman 的脚本、RHEL 安装环境获取脚本。这三个脚本的配合逻辑是从联网环境收集 rpm 包,到离线环境解压安装。基础做法是在能联网的 RHEL 机器上配置 yum 源并开启keepcache=1,把安装过程中下载的所有 rpm 包缓存到本地,然后打包拷到客户环境,离线环境下用rpm -ivh *.rpm批量安装。这比在客户环境用yum install逐个试要快得多,也避免了依赖包缺失时在离线环境下无从下手的局面。脚本细节不用自己写,但建议拿到脚本后先在测试环境完整跑一遍,确认收集的包覆盖了 PG 编译所需的所有依赖,因为不同客户的 RHEL 小版本差异可能导致依赖包清单不同。我记得第一次在客户现场跑这套脚本时,就因为 RHEL 7.5 和 7.9 的依赖差异少拷了一个libicu,PG 编译到一半报错,现场又没有网络,只能联系人重新打包再跑一次,从那以后我每次都会先在本地搭一个同版本虚拟机把脚本全流程走一遍再进客户环境,希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询