1. 当我们谈论故障转移时,究竟在讨论什么

双十一凌晨两点,电商系统的主数据库突然宕机。此时的数据库管理员有两种选择:要么摸黑登录服务器逐个执行命令(手动切换),要么让系统像自动驾驶汽车般自主接管(自动故障转移)。这就是PostgreSQL流复制环境下必须掌握的生存技能。

让我们通过真实的命令行示例,演示如何在这两种模式间游刃有余。本次技术栈限定为:PostgreSQL 14 + Patroni 2.1 + Ubuntu 20.04。


2. 手动故障转移的五指山

2.1 典型战场环境

$ tail -n 5 /var/log/postgresql/postgresql-14-main.log
FATAL:  could not access file "pg_wal/0000000100000001000000FE": No such file or directory
PANIC:  could not locate a valid checkpoint record

2.2 传统维修三板斧

# Step1 确认备库状态
$ psql -h standby1 -p 5432 -U replicator -c "SELECT pg_is_in_recovery();"
 pg_is_in_recovery 
-------------------
 t

# Step2 提升备库为主(需要执行于备库服务器)
$ pg_ctl promote -D /var/lib/postgresql/14/main
waiting for server to promote.... done

# Step3 验证新主库状态
$ psql -h new_primary -p 5432 -U postgres -c "SELECT pg_is_in_recovery();"
 pg_is_in_recovery 
-------------------
 f

# 注意:原主库恢复后需重新配置为备库

手动画重点⚠️:整个过程要求管理员对集群状态了如指掌,每次操作间隔都可能造成分钟级服务中断。就像开着老爷车换轮胎,技术简单但风险极大。


3. Patroni的自动化魔术

3.1 先来看看指挥官的装备

# /etc/patroni/config.yml 核心配置片段
restapi:
  listen: 0.0.0.0:8008
  connect_address: 192.168.1.101:8008

etcd:
  host: 192.168.1.100:2379

bootstrap:
  dcs:
    ttl: 30
    retry_timeout: 10
    maximum_lag_on_failover: 1048576
  initdb:
  - encoding: UTF8
  - data-checksums

postgresql:
  name: node1
  listen: 0.0.0.0:5432
  connect_address: 192.168.1.101:5432
  data_dir: /var/lib/postgresql/14/main
  bin_dir: /usr/lib/postgresql/14/bin
  pgpass: /tmp/pgpass
  parameters:
    max_connections: 100
    shared_buffers: 2GB

3.2 自动换胎的真实表演

# 模拟主库断电(Ctrl+Alt+Del电源键)
$ patronictl -c /etc/patroni/config.yml list
+ Cluster: pg_cluster (7016878103969147211) ------+----+-----------+
| Member | Host          | Role    | State   | TL | Lag in MB |
+--------+---------------+---------+---------+----+-----------+
| node1  | 192.168.1.101 | Leader  | running | 5  |           |
| node2  | 192.168.1.102 | Replica | running | 5  |         0 |
+--------+---------------+---------+---------+----+-----------+

# 等待20秒后再次查看
+ Cluster: pg_cluster (7016878103969147211) ------+----+-----------+
| Member | Host          | Role    | State   | TL | Lag in MB |
+--------+---------------+---------+---------+----+-----------+
| node2  | 192.168.1.102 | Leader  | running | 5  |           |
| node1  | 192.168.1.101 | Replica | stopped |    |   unknown |
+--------+---------------+---------+---------+----+-----------+

技术亮点✨:当主库宕机时,Patroni通过ETCD选举立即触发故障转移,整个过程比手动操作快至少10倍。就像特斯拉的爆胎续跑功能,乘客甚至察觉不到异常。


4. 为什么你的选择很重要

4.1 应用场景对决

  • 手动切换适用场景

    • 开发环境故障演练
    • 小型内部系统(可容忍分钟级中断)
    • 需要严格审计操作记录的场景
  • Patroni自动切换适用场景

    • 电商大促期间的核心交易库
    • 金融行业实时交易系统
    • 7x24小时运营的物联网平台

4.2 技术参数擂台

对比维度 手动切换 Patroni自动切换
响应时间 3-15分钟 5-30秒
配置复杂度 ★☆☆☆☆(简单) ★★★★☆(需分布式协调服务)
人工干预度 全程人工操作 仅需监控告警
数据一致性 可能丢失未同步事务 自动检测同步状态
故障恢复率 依赖人员技能 预设策略自动执行

5. 那些年我们踩过的坑

5.1 网络分裂陷阱

# 三节点集群遭遇网络分区
node1 (旧主) ---------×---------- node2
   \
    ×---------------- node3

# Patroni的处理逻辑
1. 多数派节点(node2+node3)触发选举
2. node3被提升为新主
3. 网络恢复后node1自动降级为备库

实战经验💡:务必配置奇数个节点(推荐3或5个),避免脑裂问题。网络延时建议保持在3ms以内。

5.2 WAL归档的暗箭

-- 创建连续归档任务
ALTER SYSTEM SET archive_mode = on;
ALTER SYSTEM SET archive_command = 'gzip < %p > /archive/%f.gz';

警示牌🚧:自动故障转移绝不意味着可以忽视基础维护,建议每日检查归档目录空间使用率。


6. 技术选择的正确姿势

  • 混合部署策略
    在大型生产环境中,可以采用Patroni自动切换为主、手动切换为辅的模式。例如核心库使用Patroni集群,报表库采用手动切换。

  • 监控三板斧

    1. Patroni REST API状态监控
    2. pg_stat_replication同步延迟
    3. ETCD集群健康检查
  • 定期灾难演练
    推荐每月执行一次完整流程:

# 模拟主库宕机测试
$ patronictl remove pg_cluster --force
$ systemctl stop patroni
# 观察备库选举过程并记录时间