Skip to content

PostgreSQL 故障转移测试

故障转移测试是验证PostgreSQL高可用架构在主库故障时,能否自动或手动切换到备库,确保业务连续性的重要手段。测试主要包括手动故障转移测试、自动故障转移测试和半自动化故障转移测试,目标是验证故障转移机制的可靠性、测量故障转移时间、验证数据一致性、验证应用程序能否自动重连以及验证监控和告警是否正常。

测试准备工作

1. 环境准备

bash
# 检查主备状态
psql -h primary_host -U postgres -c "SELECT * FROM pg_stat_replication;"
psql -h standby_host -U postgres -c "SELECT * FROM pg_stat_wal_receiver;"

# 备份当前配置
pg_dumpall -h primary_host -U postgres -f pre_test_backup.sql

# 准备测试数据
psql -h primary_host -U postgres -c "CREATE DATABASE test_db;"
psql -h primary_host -U postgres -d test_db -c "CREATE TABLE test_table (id SERIAL PRIMARY KEY, data VARCHAR(100));"
psql -h primary_host -U postgres -d test_db -c "INSERT INTO test_table (data) VALUES ('test data');"

2. 工具准备

  • psql:PostgreSQL命令行工具
  • pgbench:基准测试工具,用于模拟负载
  • patronictl:Patroni集群管理工具(如果使用Patroni)
  • HAProxy:负载均衡器(如果使用)
  • 监控工具:Prometheus+Grafana、pgAdmin等

3. 测试计划

测试场景测试步骤预期结果验证方法
主库崩溃1. 终止主库进程
2. 执行故障转移
备库晋升为主库
数据无丢失
检查备库状态
验证测试数据
网络中断1. 断开主库网络
2. 等待自动故障转移
备库晋升为主库
应用程序自动重连
检查集群状态
验证应用连接
存储故障1. 模拟主库存储故障
2. 执行故障转移
备库晋升为主库
数据一致性
验证数据完整性
检查WAL位置

手动故障转移测试

1. 基于流复制的手动故障转移

bash
# 步骤1:在备库检查主备同步状态
psql -h standby_host -U postgres -c "SELECT * FROM pg_stat_wal_receiver;"

# 步骤2:在主库插入测试数据
psql -h primary_host -U postgres -d test_db -c "INSERT INTO test_table (data) VALUES ('before failover');"

# 步骤3:模拟主库故障(终止主库进程)
pkill -9 postgres

# 步骤4:在备库执行故障转移
psql -h standby_host -U postgres -c "SELECT pg_promote();"

# 步骤5:验证备库已晋升为主库
psql -h standby_host -U postgres -c "SELECT pg_is_in_recovery();"  # 应返回f

# 步骤6:验证数据完整性
psql -h standby_host -U postgres -d test_db -c "SELECT * FROM test_table;"  # 应包含新增数据

2. 基于pg_rewind的手动故障转移

当主备差距较大时,可以使用pg_rewind快速同步:

bash
# 步骤1:模拟主库故障
pkill -9 postgres

# 步骤2:在备库晋升为主库
psql -h standby_host -U postgres -c "SELECT pg_promote();"

# 步骤3:修复原主库并使用pg_rewind同步
pg_ctl start -D /var/lib/postgresql/14/main -o "-c port=5433"
pg_rewind -D /var/lib/postgresql/14/main --source-server="host=standby_host port=5432 user=postgres"

# 步骤4:将原主库配置为新主库的备库
psql -h primary_host -p 5433 -U postgres -c "
STOP REPLICA;
ALTER SYSTEM SET primary_conninfo = 'host=standby_host port=5432 user=replicator password=password';
START REPLICA;
"

# 步骤5:验证新的主备关系
psql -h standby_host -U postgres -c "SELECT * FROM pg_stat_replication;"

自动故障转移测试

1. Patroni集群故障转移测试

bash
# 步骤1:查看Patroni集群状态
patronictl -c /etc/patroni/patroni.yml list

# 步骤2:模拟主库故障
patronictl -c /etc/patroni/patroni.yml failover

# 或直接终止主库进程
pkill -9 postgres

# 步骤3:监控故障转移过程
patronictl -c /etc/patroni/patroni.yml watch

# 步骤4:验证故障转移结果
patronictl -c /etc/patroni/patroni.yml list  # 应显示新的主库

# 步骤5:验证数据完整性
psql -h new_primary_host -U postgres -d test_db -c "SELECT * FROM test_table;"

2. PostgreSQL Automatic Failover (PAF)测试

bash
# 步骤1:检查PAF状态
pcs status

# 步骤2:模拟主库故障
pcs resource failover postgresql-master

# 步骤3:监控故障转移
pcs status

# 步骤4:验证结果
pcs status | grep postgresql-master  # 应显示在新节点上运行

应用程序验证

1. 连接字符串配置

确保应用程序使用正确的连接字符串,支持自动重连:

java
// Java连接字符串示例
String url = "jdbc:postgresql://load_balancer:5432/test_db?sslmode=require&connectTimeout=5000&socketTimeout=30000&reWriteBatchedInserts=true&autoReconnect=true";

2. 验证应用程序自动重连

bash
# 步骤1:启动应用程序并持续写入数据
java -jar test_app.jar

# 步骤2:执行故障转移
patronictl -c /etc/patroni/patroni.yml failover

# 步骤3:检查应用程序日志
grep -i "reconnect" app.log  # 应显示自动重连信息

# 步骤4:验证数据连续性
psql -h new_primary_host -U postgres -d test_db -c "SELECT count(*) FROM test_table;"  # 数据应持续增长

故障转移时间测量

1. 手动测量

bash
# 步骤1:开始计时
echo "Start time: $(date +%s.%N)" > failover_time.log

# 步骤2:执行故障转移
pkill -9 postgres
psql -h standby_host -U postgres -c "SELECT pg_promote();"

# 步骤3:结束计时
echo "End time: $(date +%s.%N)" >> failover_time.log

# 步骤4:计算故障转移时间
t1=$(grep "Start time" failover_time.log | awk '{print $3}')
t2=$(grep "End time" failover_time.log | awk '{print $3}')
echo "Failover time: $(echo "$t2 - $t1" | bc) seconds"

2. 使用监控工具测量

通过Prometheus+Grafana监控以下指标:

  • pg_stat_wal_receiver.replay_lag:备库回放延迟
  • pg_up:实例可用性
  • patroni_cluster_members:Patroni集群成员状态

故障转移测试最佳实践

1. 测试前准备

  • 通知相关团队(开发、运维、业务)
  • 备份所有配置和数据
  • 准备回滚方案
  • 确保监控和告警正常

2. 测试中注意事项

  • 记录每一步操作和结果
  • 监控系统资源使用情况
  • 检查日志文件
  • 验证数据一致性

3. 测试后验证

sql
-- 检查数据库状态
SELECT pg_is_in_recovery();

-- 检查WAL位置
SELECT pg_current_wal_lsn();

-- 验证数据完整性
SELECT * FROM test_table ORDER BY id DESC LIMIT 10;

-- 检查复制状态(如果有新的备库)
SELECT * FROM pg_stat_replication;

-- 检查连接数
SELECT count(*) FROM pg_stat_activity;

4. 恢复原主库

bash
# 修复原主库
pg_ctl start -D /var/lib/postgresql/14/main

# 将原主库配置为新主库的备库
psql -h primary_host -U postgres -c "
STOP REPLICA;
ALTER SYSTEM SET primary_conninfo = 'host=new_primary_host port=5432 user=replicator password=password';
START REPLICA;
"

# 验证新的主备关系
psql -h new_primary_host -U postgres -c "SELECT * FROM pg_stat_replication;"

常见故障场景测试

1. 主库崩溃

测试步骤

  1. 终止主库进程
  2. 执行故障转移
  3. 验证备库晋升为主库

预期结果

  • 故障转移时间 < 30秒
  • 数据无丢失
  • 应用程序自动重连

2. 网络中断

测试步骤

  1. 断开主库网络连接
  2. 等待自动故障转移
  3. 恢复主库网络

预期结果

  • 高可用软件能检测到网络故障
  • 自动切换到备库
  • 原主库恢复后能作为备库重新加入集群

3. 存储故障

测试步骤

  1. 模拟主库存储故障(挂载只读或断开存储)
  2. 执行故障转移
  3. 验证数据一致性

预期结果

  • 故障转移成功
  • 数据一致
  • 无数据丢失

监控和告警验证

1. 监控指标验证

sql
-- 检查监控指标是否正常
SELECT 
  datname,
  xact_commit,
  xact_rollback,
  blks_read,
  blks_hit
FROM pg_stat_database;

2. 告警验证

  • 主库宕机告警
  • 故障转移完成告警
  • 备库延迟告警
  • 应用连接失败告警

常见问题处理

1. 故障转移后数据不一致

问题:故障转移后,备库数据与原主库不一致

解决方法

  • 检查WAL归档是否完整
  • 使用pg_rewind同步原主库
  • 重新初始化备库

2. 应用程序无法自动重连

问题:故障转移后,应用程序无法自动重连到新主库

解决方法

  • 检查连接字符串配置
  • 确保应用程序支持自动重连
  • 检查负载均衡器配置

3. 故障转移时间过长

问题:故障转移时间超过预期(>30秒)

解决方法

  • 优化备库配置(如wal_buffers、checkpoint_completion_target)
  • 调整高可用软件的检测间隔
  • 减少备库回放延迟

测试报告模板

1. 测试基本信息

项目内容
测试日期YYYY-MM-DD
测试人员姓名
测试环境生产/测试
高可用架构Patroni/PAF/自定义
主库版本PostgreSQL 14.5
备库数量2

2. 测试结果

测试场景测试结果故障转移时间数据一致性应用重连
主库崩溃成功/失败XX秒一致/不一致成功/失败
网络中断成功/失败XX秒一致/不一致成功/失败
存储故障成功/失败XX秒一致/不一致成功/失败

3. 问题和改进

问题描述严重程度解决方法负责人
故障转移时间过长高/中/低调整检测间隔张三
应用重连失败高/中/低优化连接字符串李四

常见问题(FAQ)

Q1:如何测量故障转移时间?

A1:可以通过以下方式测量:

  • 使用脚本记录故障转移前后的时间戳
  • 通过监控系统查看主库宕机到备库晋升的时间
  • 使用应用程序日志记录重连时间

Q2:故障转移测试会影响生产环境吗?

A2:会,因此:

  • 应在维护窗口进行测试
  • 提前通知相关团队
  • 准备回滚方案
  • 建议先在测试环境验证

Q3:如何验证故障转移后的数据一致性?

A3:验证方法:

  • 比较故障转移前后的数据量
  • 检查关键业务数据
  • 使用pg_verifybackup工具验证备份
  • 检查WAL位置是否一致

Q4:自动故障转移失败怎么办?

A4:处理步骤:

  1. 手动执行故障转移
  2. 检查高可用软件日志
  3. 分析失败原因
  4. 修复问题后重新测试

Q5:如何优化故障转移时间?

A5:优化方法:

  • 调整高可用软件的检测间隔
  • 优化备库配置,减少回放延迟
  • 使用更快的存储设备
  • 减少主库的WAL生成速率

Q6:故障转移后需要做什么?

A6:后续工作:

  • 验证数据一致性
  • 检查应用程序连接
  • 将原主库恢复为备库
  • 更新监控配置
  • 记录测试结果

Q7:如何模拟主库故障?

A7:模拟方法:

  • 终止主库进程:pkill -9 postgres
  • 断开网络连接:iptables -A INPUT -p tcp --dport 5432 -j DROP
  • 挂载存储为只读:mount -o remount,ro /var/lib/postgresql

Q8:如何准备故障转移测试?

A8:准备工作:

  • 备份当前配置和数据
  • 准备测试计划和测试用例
  • 通知相关团队
  • 确保监控和告警正常
  • 准备回滚方案