一、当你的数据库需要"瘦身":流复制缩容的必要场景
我们的数据库集群就像一支不断扩张的乐队,随着业务发展不断加入新乐手(从库节点)。但当演奏场景从大型音乐会换成小剧场时,这些冗余的乐手反而会影响整体配合。最常见的三种缩容需求场景:
资源过剩型瘦身
某电商平台大促后,原本支撑高并发的5节点集群需要回归日常运营状态。此时可保留3节点保障基础可用性,将两个从库节点资源释放给其他业务架构优化型调整
某社交平台将原来的多地双活架构调整为单元化部署,需要下线异地灾备节点。这时需确保下线节点不会影响本地集群运行问题节点退役
当某个从库节点出现硬件故障或性能瓶颈时,直接将其移出复制集群比维修更高效。曾有DBA遇到RAID卡故障的物理机,通过缩容操作在15分钟内完成故障隔离
# 示例:查看当前复制集群状态(PostgreSQL 14)
psql -h primary_node -U replicator -c "
SELECT client_addr AS 节点IP,
state AS 状态,
write_lag + flush_lag + replay_lag AS 总延迟,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(),replay_lsn)) AS 未应用数据量
FROM pg_stat_replication;"
# 输出示例:
# 节点IP | 状态 | 总延迟 | 未应用数据量
#-------------+---------+--------+--------------
# 192.168.1.2 | streaming | 2.1s | 128 MB
# 192.168.1.3 | streaming | 15.4s | 2.1 GB <-- 需移除的异常节点
二、安全下线
1. 术前检查不可少
如同外科医生术前要确认患者体征,DBA需要确认以下关键指标:
- 目标节点复制延迟不超过5秒
- 主库未处于基础备份状态
- 所有业务读写都配置了重试机制
- 维护窗口时间足够完成操作
-- 预检完整脚本(主库执行)
DO $$
DECLARE
repl_status RECORD;
BEGIN
-- 检测是否处于备份状态
IF EXISTS (SELECT 1 FROM pg_stat_activity WHERE query LIKE 'pg_basebackup%') THEN
RAISE EXCEPTION '存在正在运行的基础备份';
END IF;
-- 检测所有从库状态
FOR repl_status IN
SELECT client_addr, state, pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS lag_bytes
FROM pg_stat_replication
LOOP
IF repl_status.lag_bytes > 500000000 THEN -- 超过500MB视为异常
RAISE NOTICE '节点 % 存在 %.2f MB的延迟',
repl_status.client_addr,
repl_status.lag_bytes::numeric/1048576;
END IF;
END LOOP;
END $$;
2. 优雅停复制的正确姿势
突然中断复制就像急刹车,可能造成数据碎片。正确操作应该是:
# 在待移除的从库节点执行
pg_ctl pause # 暂停数据接收(PostgreSQL 14新特性)
pg_ctl stop -m smart # 优雅关闭实例
# 主库上释放复制槽(防止WAL堆积)
psql -h primary_node -c "
SELECT pg_drop_replication_slot(slot_name)
FROM pg_replication_slots
WHERE active_pid IS NULL;"
3. 配置文件的蝴蝶效应
修改主库的pg_hba.conf时,老DBA容易踩的坑:
- 禁用IP段而非精确IP导致误杀
- 忘记reload配置直接重启
- 未保留变更记录
# 安全修改示例
TIMESTAMP=$(date +%Y%m%d%H%M)
cp /var/lib/pgsql/14/data/pg_hba.conf /backup/pg_hba.conf.$TIMESTAMP
# 使用精确锁定(建议通过配置管理工具执行)
sed -i "/^host replication replicator 192.168.1.3\/32/d" /var/lib/pgsql/14/data/pg_hba.conf
# 优雅加载配置
psql -h localhost -U postgres -c "SELECT pg_reload_conf()"
三、防踩坑指南:血泪经验总结
1. 幽灵复制槽的诅咒
某次缩容操作后三天,主库突然出现磁盘告警。追查发现遗留的复制槽仍在持续堆积WAL日志。这要求我们必须:
-- 缩容后的主库检查脚本
WITH dead_slots AS (
SELECT slot_name,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) as retained_size
FROM pg_replication_slots
WHERE active = false
)
SELECT * FROM dead_slots WHERE retained_size > '1GB';
2. 负载均衡器的无声背叛
下架节点后,运维人员经常忘记同步调整HAProxy或Nginx配置。推荐采用自动化联动:
# Ansible剧本示例(片段)
- name: 更新负载均衡配置
hosts: load_balancer
tasks:
- name: 从后端池移除节点
lineinfile:
path: /etc/haproxy/haproxy.cfg
regexp: 'server pg-node3 '
state: absent
notify: reload haproxy
handlers:
- name: reload haproxy
systemd:
name: haproxy
state: reloaded
四、延伸战场:故障节点的重生之术
对于可能需要重新加入集群的节点,聪明的DBA会先做pg_rewind:
# 数据分歧修复示例
pg_ctl stop
rm -rf /var/lib/pgsql/14/data/*
pg_basebackup -h primary_node -U replicator -D /var/lib/pgsql/14/data -X stream
pg_ctl start
五、技术选型的双面性
流复制缩容的优点
- 毫米级精度:基于WAL日志的同步机制
- 热操作可能性:部分场景可在线完成
- 生态完整:丰富的监控工具链
需要警惕的短板
- 级联复制拓扑中可能引发连锁反应
- 大事务处理时需要更高超的平衡技巧
- 对网络抖动的容错性较云原生方案弱
六、写给未来的自己:最佳实践备忘录
- 变更三板斧:操作前拍快照、操作中做记录、操作后留监控
- 熔断机制:在下线过程中预设可快速回滚的锚点
- 业务视角验证:不只是数据库状态正常,更要确认应用日志无异常
- 容量规划:缩容后的集群剩余资源应有30%安全余量
评论