ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

PostgreSQL高可用实战:repmgr+keepalived主从复制与自动故障转移

PostgreSQL高可用实战:repmgr+keepalived主从复制与自动故障转移 1. 先说结论这套架构到底解决什么问题看到这个标题很多刚接触PostgreSQL的同学第一反应是数据库不是装好就能用吗为什么要搞主从复制还要再套一个keepalived我2018年第一次在生产环境做PG高可用时也是这个想法直到某天凌晨两点主库磁盘满掉、业务直接停摆才真正理解“高可用”这三个字的分量。PostgreSQL本身是一个单机数据库它没有内置的自动故障转移能力。你可以用自带的流复制搭出一主一备但备库不会主动变成主库应用也不能自动把连接切过去。这套方案要解决的就是两个核心问题数据冗余主库的数据实时同步到备库主库出故障时数据不丢或尽量少丢。自动切换主库故障后备库自动提升为新主库业务通过VIP虚拟IP无感知地切换到新主库上继续跑。这套方案的主角是三个PostgreSQL负责数据存储和流复制repmgr负责主备关系管理、监控和故障时的角色提升keepalived负责VIP漂移。repmgr管“谁能当主”keepalived管“流量怎么过去”两者各管一层配合起来就是一个完整的数据库高可用闭环。我写的这篇东西适合三类人一是刚接手PG数据库运维、想搭一套靠谱高可用架构的DBA二是公司没有专职DBA、需要自己动手的运维或后端开发三是为了应付技术面试、想把这个经典组合讲明白的求职者。我会按从零开始的顺序把安装、配置、故障演练、踩坑全部走一遍所有命令都是我在CentOS 7.9和Rocky Linux 8上实测过可用的。提示本文所有命令和配置均在RHEL系发行版上验证Debian/Ubuntu系的路径和包管理器略有差异但思路完全一致照着调整即可。2. 方案选型为什么是repmgr keepalived而不是Patroni或Pacemaker2.1 三个方案的横向对比在动手安装之前先花点时间聊方案选型。PostgreSQL的高可用方案现在主流有三类repmgr keepalived、Patroni etcd/consul、Pacemaker corosync通常配DRBD或共享存储。我见过太多人上来就装装到中途发现架构不匹配推倒重来所以在第一步就把优劣说清楚。特性repmgr keepalivedPatroni etcd/consulPacemaker corosync架构复杂度低两个组件较高需额外维护一致性组件高集群资源管理复杂对脑裂的处理依赖repmgr判断脚本兜底通过etcd/consul分布式锁有Fencing机制更严格学习成本中等较高高适用规模中小型业务2~3节点中大型业务多节点动态选主传统企业与存储强绑定自动故障转移支持repmgrd守护进程支持Raft共识支持资源约束2.2 我这套方案的优势和边界repmgr keepalived最核心的优势是轻。它不需要额外引入一套分布式协调组件也没有那么多资源约束概念一台主库、一台备库、一个VIP三个组件就能转起来。对于用户量几万、QPS几千的业务这个架构完全够用而且排障链路短数据库层的问题看repmgr日志网络层的问题看keepalived日志心智负担很小。那它的边界在哪里最大的风险是脑裂也就是主备都认为自己是主、都尝试对外提供服务。keepalived的VRRP协议只能在网络层面保证同一时刻只有一个节点持有VIP但如果网络出现瞬断两个节点可能同时进入MASTER状态。repmgr这边repmgrd在检测到主库失联后会尝试将备库提升为primary但网络抖动也可能触发误切换。应对这个风险业界通用的做法是加仲裁节点。最少用三台机器仲裁节点不跑数据库只参与keepalived的投票和repmgr的见证。条件不允许的话至少要在repmgr配置里关闭自动切换、改为半自动failovermanual或者把repmgrd的检测时间和重试次数调大用时间维度过滤瞬断。2.3 什么时候不要选这套方案我必须说清楚如果你的业务对数据一致性要求极其苛刻——比如金融交易、订单流水RPO接近零那这套架构不达标。repmgr的默认流复制是异步的主库崩溃瞬间未同步的事务可能丢失。这时候你该考虑同步复制synchronous_commit on synchronous_standby_names或者直接上Patroni配同步节点、甚至上共享存储Pacemaker。另外如果节点超过三个、需要动态扩缩容Patroni的Raft选主机制明显更顺手。我实际的经验是3节点以下、没有专职DBA、想快速交付一套能用的高可用环境repmgr keepalived是最优解节点多、要求强一致、有专门基础架构团队直接Patroni别犹豫。剩下的内容都围绕前者展开。3. 环境准备三件套缺一不可3.1 主机规划与版本确认我先给出一套我在生产环境验证过的标准规划。两台数据库节点加一台可选的监控见证节点CPU内存按业务量来至少2C4G起步。操作系统用的是Rocky Linux 8.8CentOS 7.9同样适用只是PG编译依赖会老一点。主机名IP角色说明pg-primary192.168.10.11主库节点初始主库跑PG repmgr keepalivedpg-standby192.168.10.12备库节点初始备库跑PG repmgr keepalivedpg-witness192.168.10.13见证节点可选跑repmgr witness keepalived仲裁VIP192.168.10.100虚拟IP应用连接入口正常时绑定在主库节点这里有个很多人踩过的坑VIP网段必须和业务网卡在同一个二层网络不然VRRP广播报文传不过去keepalived漂移根本不会发生。如果你跨机房做多活需要单独规划三层路由那是另一套方案了本文不展开。PostgreSQL版本方面我做这套环境时用的16.3。选16的原因有三个逻辑复制在16上重大改进、流复制协议稳定、repmgr官方对16的支持已经非常成熟。如果你有历史包袱在跑11或12repmgr 5.x也有对应支持别盲目升大版本PG的大版本升级不是小事。3.2 系统基础配置10分钟搞定主机名、hosts解析、免密SSH、时间同步、防火墙这五项是集群的“地基”任何一个出问题都会让你在后面排查到怀疑人生。第一设置主机名并写入hosts。keepalived和repmgr都是靠主机名通信的主机名不一致直接报错。hostnamectl set-hostname pg-primary cat /etc/hosts EOF 192.168.10.11 pg-primary 192.168.10.12 pg-standby 192.168.10.13 pg-witness EOF第二配置双节点免密SSH登录。repmgr的standby clone操作要通过SSH在备库上执行密码交互会导致脚本卡死。ssh-keygen -t rsa -b 4096 -N -f ~/.ssh/id_rsa ssh-copy-id pg-primary ssh-copy-id pg-standby第三时间同步。流复制对时间偏差没那么敏感但事务时间戳和日志排查需要一致的时间线用chrony同步一下更稳妥。dnf install -y chrony systemctl enable --now chronyd chronyc sources -v第四关闭SELinux放行或关闭防火墙。生产环境安全要求高的话只放行必要的端口PostgreSQL的5432repmgr的SSH通信端口keepalived的VRRP协议通常是IP协议112号以及Windows下组播地址224.0.0.18。我为了演示方便直接关掉了防火墙但你要知道哪些端口是必需的。setenforce 0 sed -i s/^SELINUX.*/SELINUXdisabled/ /etc/selinux/config systemctl stop firewalld systemctl disable firewalld第五确认两台节点的locale和时区一致避免复制时文本编码问题。timedatectl set-timezone Asia/Shanghai localectl set-locale LANGen_US.UTF-83.3 PostgreSQL安装编译还是二进制包这一步我纠结过很久。二进制包安装快、省心但自定义编译参数受限源码编译灵活、可控但费时且依赖多。如果你用的是CentOS 7.9PGDG官方源里就有编译好的RPM包直接装如果你用的是Rocky 8/9或者想用PG 16的最新小版本RPM包也覆盖到了。我的建议是能用RPM包就别编译生产环境稳定优先别在安装上折腾。dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm dnf -y install postgresql16-server postgresql16但要注意PGDG源在安装后不会自动初始化数据目录需要手动执行/usr/pgsql-16/bin/postgresql-16-setup initdb systemctl enable --now postgresql-16初始化完成的第一步就是修改postgres用户密码和设置默认连接su - postgres psql -c ALTER USER postgres WITH PASSWORD YourStrongPass; exit到这里单机PG已经跑起来了。但注意这只是起点。接下来要做的所有配置都是为了让它具备“被管理”的条件。4. PostgreSQL基础配置高可用的地基4.1 必须改的postgresql.conf参数repmgr的主从复制基于PostgreSQL的WAL日志流复制。要让复制正常工作主库必须开启wal_level、配置足够的max_wal_senders和wal_keep_size备库要配置hot_standby。这些参数在PG 16里默认值比老版本友好但高可用场景下仍要显式确认。su - postgres vi /var/lib/pgsql/16/data/postgresql.conf我贴上生产环境经过验证的核心配置listen_addresses * port 5432 max_connections 300 wal_level replica max_wal_senders 10 max_replication_slots 10 wal_keep_size 1GB hot_standby on synchronous_commit local这里重点解释两个容易被忽视的参数max_wal_senders备库连接主库拉取WAL时每个备库至少占用一个WAL sender进程。如果只搭一主一备设10个已经富余但如果你后续加节点或者做逻辑复制这个值就决定上限。wal_keep_size主库保留多少WAL日志给落后的备库追上。如果备库断开太久超过这个值还没追上的话备库只能重新全量clone这在生产中属于比较严重的故障。条件允许还可以额外配置archive_mode on和archive_command把WAL归档到独立存储进一步增强容错。4.2 pg_hba.conf复制用户的授权流复制需要一个专门的复制账号一般叫repl。PostgreSQL文档推荐单独建一个最小权限用户只用REPLICATION权限不要用超级用户。CREATE ROLE repl WITH REPLICATION LOGIN PASSWORD ReplPass123;然后编辑pg_hba.conf加入下面两行。注意顺序pg_hba.conf是按顺序匹配的复制账号的规则要放在数据库普通用户规则之前。host replication repl 192.168.10.11/32 md5 host replication repl 192.168.10.12/32 md5 host all all 192.168.10.0/24 md5配置完成后重启PG使参数生效systemctl restart postgresql-16验证复制连接是否正常可以在主库本地执行/usr/pgsql-16/bin/pg_isready -h 192.168.10.11 -p 5432 psql -h 192.168.10.11 -U repl -d postgres -c SELECT 1;能查到结果说明复制账号和监听都没问题。这个动作做完PostgreSQL层面就具备了被repmgr接管的基础条件。注意PostgreSQL的listen_addresses如果没设置成*或明确网段备库通过TCP拉取WAL会一直卡在“连接超时”。很多新手搭不起来主从第一嫌疑就是这个参数。5. repmgr主从复制搭建全流程5.1 repmgr的安装与版本匹配repmgr的版本必须和PostgreSQL大版本匹配。PG 16对应repmgr 5.4PG 15用repmgr 5.3。如果你装了PG 16却用repmgr 5.2的老包启动的时候会直接报repmgr: fatal: unsupported PostgreSQL major version这个错太典型了我踩过一次。PGDG源里直接有repmgr的RPM包安装即可dnf install -y repmgr16验证版本repmgr --version # repmgr version 5.4.15.2 repmgr.conf一张一张参数说清楚repmgr的配置文件路径我放在/etc/repmgr/16/repmgr.conf。两个数据库节点的配置文件几乎一样唯一不同的是node_id和node_name。我贴出主库的完整配置node_id1 node_namepg-primary conninfohostpg-primary port5432 userrepl dbnamepostgres connect_timeout5 data_directory/var/lib/pgsql/16/data failoverautomatic promote_command/usr/pgsql-16/bin/repmgr standby promote -f /etc/repmgr/16/repmgr.conf --log-level DEBUG follow_command/usr/pgsql-16/bin/repmgr standby follow -f /etc/repmgr/16/repmgr.conf --log-level DEBUG monitoring_historyyes log_levelDEBUG log_file/var/log/repmgr/repmgr.log ssh_options-o ConnectTimeout5 -o StrictHostKeyCheckingno逐个说下重点参数conninfo这里的主机名必须是两台机器都能解析的名字。我直接用了hosts里的pg-primary别用IP因为repmgr的节点身份是靠node_name和conninfo里的host对应的IP切换时容易出幻觉问题。failoverautomatic开启自动切换。如果不放心可以先设成manual观察repmgr的判定逻辑后再打开。我第一次搭生产环境就吃了自动切换的亏网络抖动导致误切换从那以后我强烈建议先手动演练几轮再开automatic。promote_command和follow_command这是repmgr在切换时执行的系统命令负责把备库提升为新主库、或者把原主库重新作为备库跟随新主库。命令里-f指定配置文件别省。log_levelDEBUG调试阶段建议开DEBUG以后稳定了可以改成INFO否则日志刷得太快容易掩盖关键信息。备库的配置文件只改两处node_id2、node_namepg-standby其余完全一致。两个节点都执行mkdir -p /var/log/repmgr chown -R postgres:postgres /var/log/repmgr5.3 主库注册repmgr primary register在主库上以postgres用户执行su - postgres /usr/pgsql-16/bin/repmgr -f /etc/repmgr/16/repmgr.conf primary register这一步做了什么它在repmgr的元数据表里登记主库信息创建repmgr相关的schema和表。执行成功后查询确认/usr/pgsql-16/bin/repmgr -f /etc/repmgr/16/repmgr.conf cluster show输出里应该有ID | Name | Role | Status | Upstream | Location | Priority | Timeline | Connection string --------------------------------------------------------------------------------------------- 1 | pg-primary | primary | * running | - | default | 100 | 1 | hostpg-primary ...注意Status那一列必须是* running星号表示这个节点是当前的主节点。如果显示? unreachable大概率是conninfo或者SSH问题先回头检查hosts解析和免密。5.4 备库clone从头搭建流复制备库上PostgreSQL已经装好但数据目录是空的或者还是initdb初始化的原始状态。repmgr提供了一个命令直接通过SSH从主库拉取全量数据并自动搭建流复制su - postgres /usr/pgsql-16/bin/repmgr -h pg-primary -U repl -d postgres -f /etc/repmgr/16/repmgr.conf standby clone这个命令本质做了四件事在主库上执行pg_basebackup把主库数据文件完整拷贝到备库。在备库生成standby.signal文件告诉PG启动时进入备库模式。自动写入主库的连接信息和replication slot。更新repmgr元数据把备库登记进集群。clone完成后启动备库的PG服务systemctl start postgresql-16然后注册备库/usr/pgsql-16/bin/repmgr -f /etc/repmgr/16/repmgr.conf standby register到这里一个基于repmgr管理的主从复制就建好了。验证一下/usr/pgsql-16/bin/repmgr -f /etc/repmgr/16/repmgr.conf cluster show应该看到两个节点主库* running备库running as standby。再深入验证复制是否在实时同步。在主库建一张测试表并插入数据psql -c CREATE TABLE ha_test (id serial primary key, ts timestamptz default now()); psql -c INSERT INTO ha_test (ts) VALUES (now());在备库查询psql -c SELECT * FROM ha_test;能查到刚插入的记录说明流复制链路完全打通。如果查不到别急着往下走看主库的pg_stat_replication视图SELECT client_addr, state, sync_state, replay_lag FROM pg_stat_replication;正常情况下state是streamingreplay_lag接近0或为空。如果是catchup状态说明备库还在追WAL等一会儿再查。5.5 开启repmgrd守护进程repmgr装好只是“管理工具”真正实现自动切换得靠后台守护进程repmgrd。它在两个节点上都要启动一个负责监控主库心跳一个负责监控备库复制状态systemctl enable --now repmgrd-16 systemctl status repmgrd-16repmgrd启动后每间隔reconnect_attempts和reconnect_interval默认在配置文件里可以自行调整都会检查上游节点状态。我用过一个比较稳妥的参数组合reconnect_attempts6 reconnect_interval10意思是在60秒内连续6次连接失败才判定主库失联。这样普通的网络抖动不会触发切换而真正的宕机又能在一分钟内被识别。提示repmgrd的日志和repmgr的命令日志是两个概念。前者在/var/log/repmgr/repmgrd.log后者在/var/log/repmgr/repmgr.log。排障时看错文件会浪费大量时间我经历过一次。6. keepalived故障转移配置6.1 keepalived是干什么的PostgreSQL层的主备切换做完了但如果应用的数据库连接地址还是指向原来的物理IP一切等于白搭。keepalived解决的就是这个问题它对外提供一个虚拟IPVIPVIP平时绑定在主库节点当主库故障、备库提升后VIP自动漂移到备库节点应用连接的IP不用变就能无缝切换到新主库上。keepalived的核心是VRRP协议。简单理解组内的节点周期性互相发心跳报文谁的优先级高谁就是MASTER、持有VIPMASTER挂了BACKUP节点中优先级最高的顶上。这里的关键点来了keepalived只知道节点死没死不知道是数据库死还是机器死。所以必须写脚本去探测数据库和repmgr的状态脚本探测异常时主动降低本节点优先级把VIP让给健康节点。6.2 安装keepaliveddnf install -y keepalived systemctl enable keepalived6.3 主库的keepalived配置配置文件在/etc/keepalived/keepalived.conf。我直接贴出经过生产验证的完整版global_defs { router_id PG_HA_01 enable_script_security } vrrp_script check_pg_alive { script /etc/keepalived/check_pg_alive.sh interval 3 timeout 3 fall 2 rise 2 } vrrp_instance VI_DB { state MASTER interface eth0 virtual_router_id 51 priority 150 advert_int 1 authentication { auth_type PASS auth_pass 8aK9#zFq } virtual_ipaddress { 192.168.10.100/24 dev eth0 label eth0:1 } track_script { check_pg_alive } }参数逐个说明state MASTER主库配置成MASTER。注意它只在启动时决定初始状态后续靠优先级动态调整。priority 150主库的优先级。备库我会配100。优先级高的在VRRP竞选里胜出。virtual_router_id 51同一个集群内的keepalived节点这个值必须一致否则分不到一个组里。auth_passVRRP认证密码同一组必须一致长度不超过8位。advert_int 1VRRP广播间隔单位秒。间隔越小切换越快但过于频繁会增大网络负担1秒是通用值。fall 2和rise 2脚本连续失败2次才认为故障连续成功2次才恢复。这个参数专门防抖动。备库的配置只有两处不同state BACKUP、priority 100其他一模一样。6.4 VRRP脚本怎么写这是整个方案里最需要花心思的地方。脚本的目标是数据库活着、repmgr确认本节点是主本节点才有资格持有VIP。我写了一个保守但可靠的版本#!/bin/bash # /etc/keepalived/check_pg_alive.sh PG_USERpostgres # 1. 检查postgres进程是否存活 pgrep -f postgres.*-D /var/lib/pgsql/16/data /dev/null 21 if [ $? -ne 0 ]; then exit 1 fi # 2. 用psql探测数据库是否真正可连接 psql -U $PG_USER -h 127.0.0.1 -p 5432 -c SELECT 1; /dev/null 21 if [ $? -ne 0 ]; then exit 1 fi # 3. 如果repmgr可用确认本节点是否为主节点 if [ -x /usr/pgsql-16/bin/repmgr ]; then NODE_TYPE$(/usr/pgsql-16/bin/repmgr -f /etc/repmgr/16/repmgr.conf node check 2/dev/null) echo $NODE_TYPE | grep -q primary if [ $? -ne 0 ]; then exit 1 fi fi # 4. 检查主从握手是否正常可选防止主库客户端连不上备库 psql -U $PG_USER -h 127.0.0.1 -p 5432 -c SELECT COUNT(*) FROM pg_stat_replication; /dev/null 21 exit 0脚本的第三个判断是这个方案的精髓。当repmgr完成角色切换后原主库的repmgr会把它标记为standby脚本就会让本节点的优先级自动失效VIP立刻从残废的原主库漂移到健康的新主库上。这样就把“数据库层切换”和“网络层切换”绑在了一起。脚本给执行权限并保证postgres用户能通过localhost免密连接在pg_hba.conf中配置host all postgres 127.0.0.1/32 trust或者用.pgpass文件chmod x /etc/keepalived/check_pg_alive.sh chown root:root /etc/keepalived/check_pg_alive.sh6.5 验证VIP绑定启动keepalived后在主库上检查systemctl restart keepalived ip addr show eth0 | grep 192.168.10.100看到VIP绑定在主库的eth0上inet 192.168.10.100/24 scope global eth0:1。在备库上同样的命令应该没有任何输出。至此整套架构已经搭建完毕流复制在跑repmgr在监控keepalived在守门。接下来就是最激动人心也最吓人的环节——故障演练。7. 故障演练主库挂了到底会发生什么7.1 模拟主库数据库进程崩溃先演练最常见的情况主库的postgres进程突然崩溃相当于进程被OOM Killer干掉机器本身还活着。在主库执行pkill -9 postgres等30秒左右在备库和witness节点观察变化。预期发生的事件链是这样的repmgrd探测到主库连接失败。连接重试次数达到阈值后它认为主库失联。repmgrd提升备库。它执行standby promote备库从只读模式切换为读写模式。keepalived脚本探测失败。主库的postgres进程已经没了check_pg_alive.sh返回非零主库keepalived的优先级被强制降低。VRRP切换。备库的keepalived发现主库节点不再广播或优先级低于自己抢到VIP。验证是否切换成功# 在备库检查角色 /usr/pgsql-16/bin/repmgr -f /etc/repmgr/16/repmgr.conf cluster show # 在备库检查VIP ip addr show eth0 | grep 192.168.10.100如果一切顺利你会在备库上同时看到repmgr标记它为新primary并且VIP已经绑在这台机器的网卡上。这时我从另一台应用服务器连接VIP执行写操作psql -h 192.168.10.100 -U testapp -d appdb -c INSERT INTO ha_test (ts) VALUES (now());能写入说明业务已经无缝切到新主库。7.2 原主库恢复后怎么重归集群这是大多数人到这一步就卡住的地方。直接把原主库的原进程启动起来是不行的因为此时集群里已经有一个新主了原主必须作为备库重新加入。步骤如下在原主库节点systemctl start postgresql-16然后执行repmgr的follow命令让它跟随新主库su - postgres /usr/pgsql-16/bin/repmgr -f /etc/repmgr/16/repmgr.conf standby follow这个命令会重新建立到新主库的流复制连接。如果原主库的WAL和数据落后太多repmgr会提示需要重新clone那就重复第5.4节的standby clone操作会覆盖本机数据目录谨慎确认。恢复完成后再看看集群状态/usr/pgsql-16/bin/repmgr -f /etc/repmgr/16/repmgr.conf cluster show输出里应该显示两个节点新主库是primary原主库是standby。然后回到新主库上执行/usr/pgsql-16/bin/repmgr -f /etc/repmgr/16/repmgr.conf primary register --force为什么要--force因为repmgr元数据里之前记录了原主库的primary信息现在角色变了需要强制覆盖旧的记录。7.3 演练发现的两个真实教训第一次演练我就踩坑了。我kill掉主库进程后备库提升成功了但VIP没有漂移过来。排查发现是脚本里的repmgr node check命令在角色切换的瞬间返回了“standby”脚本直接exit 1keepalived认为备库也不是“健康的primary”于是两边都没人持有VIP。解决办法是去掉脚本里对repmgr node check的强依赖只在数据库进程存活检查通过的前提下做软判断或者给脚本加一个“容错窗口期”——切换刚完成的几十秒内只要数据库能正常读写就允许备库持有VIP。第二个教训是failover触发时间太短。默认的reconnect_attempts3, reconnect_interval5意味着15秒就判定故障我模拟网络抖动时直接把业务打断了。后来改成了reconnect_attempts6, reconnect_interval10再加上keepalived脚本的fall 2整个切换窗口变成了60秒左右抖动基本都被过滤掉了。8. 常见问题与实战排查速查表8.1 六个高频问题的现场实录拼了这么多我相信总有一部分读者会卡在某个环节。把我这些年遇到的问题整理成速查表按症状给出定位和解决方案症状可能原因排查命令 / 手段解决办法standby clone失败报pg_basebackup: could not connect to server主库pg_hba.conf没放行复制用户、或listen_addresses不是*psql -h 主库IP -U repl -d postgres -c SELECT 1;检查监听地址、pg_hba.conf加复制规则并reload备库能启动但复制状态一直是catchupWAL保留量不足备库落后太多SELECT * FROM pg_stat_replication;增大wal_keep_size必要时重新clonerepmgrd启动报ERROR: node is not registered备库没有执行standby registerrepmgr cluster show执行standby registerkeepalived日志报VRRP is in fault statekeepalived脚本返回非零或网卡没择定systemctl status keepalived、journalctl -u keepalived检查脚本exit code检查网卡名是否和配置一致VIP漂移后新主库连不上、connection refused新主库的pg_hba.conf没有放行VIP网段或者listen_addresses不含VIPpsql -h VIP -U testapp -d appdb确认新主库的listen_addresses *、pg_hba.conf里有VIP对应网段主库恢复后执行standby follow报unable to connect to remote node新主库的防火墙或pg_hba.conf没放行原主库IP在恢复节点测试psql -h 新主库IP调整新主库的pg_hba.conf并SELECT pg_reload_conf();8.2 几个容易忽略的细节除了上面这些具体问题还有几个不能叫“坑”但非常重要的小细节。第一个是备份。高可用不是备份的替代品就算是主从集群也要定期做pg_dump或pg_basebackup的异地备份。万一两个节点同时挂了只能靠备份恢复这时候没有备份就等于归零。第二个是监控告警。集群能自动切换不等于不需要人盯着。我在生产里把repmgr和keepalived的状态都接入了Zabbix告警主备角色变化、VIP漂移、复制延迟超过30秒都会丁丁报警。自动机制解决“快”人处理“对”两者缺一不可。第三个是脑裂的物理兜底。条件允许的话在备库的脚本里加一道“双保险”如果备库认为自己该提升执行promote前先SSH到主库节点执行pg_ctl stop -m immediate确保原主库不会继续写数据。虽然这会让恢复时间变长几秒但能极大降低“双主”的风险。我的生产环境就是这么配的稳妥比速度重要。8.3 这套集群适合什么样的人持续演进最后我想说一嘴这套repmgr keepalived的架构装好之后你不是就“毕业”了。它有清晰的演进路径上了三节点之后可以考虑引入etcd做仲裁把repmgr的failover和仲裁逻辑完全剥离开业务再大一点可以升级到Patroni享受它更精细的调度策略和REST API。装集群的过程本质上是理解“数据库高可用到底在解决什么问题”的过程理解了这个任何方案在你眼里都是同一道题的解法。我个人的体会是这套架构最值钱的地方不是那几个安装命令而是故障出现时你能有条不紊地判断问题在数据库层还是网络层。第一次做主库故障演练时手心冒汗多演练几次后半夜收到告警也能从容处理。希望这篇内容能帮你少走一些弯路把集群搭扎实。
返回列表