一、为什么需要自动故障转移

数据库高可用是生产环境中的刚需。想象一下,半夜三点数据库主节点突然宕机,运维人员睡眼惺忪地爬起来手动切换——这种场景谁都不想遇到。PostgreSQL虽然自带流复制,但故障转移需要人工干预,这时候就需要像Patroni这样的工具来帮我们实现自动化。

Patroni是一个用于管理PostgreSQL高可用集群的Python工具,它通过分布式共识系统(比如etcd)来协调故障转移。etcd则是一个可靠的键值存储,常用于服务发现和配置共享。这俩搭档起来,能让PostgreSQL集群在主节点挂掉时,自动选举新的主节点,业务几乎无感知。

二、环境准备与组件安装

1. 基础环境

假设我们有三台服务器(192.168.1.10、192.168.1.11、192.168.1.12),操作系统是CentOS 7。

# 在所有节点上安装依赖
yum install -y python3 python3-devel gcc postgresql12 postgresql12-server postgresql12-contrib

2. 安装etcd集群

etcd需要部署在奇数个节点上以实现高可用。以下是在192.168.1.10上的配置示例:

# 下载etcd
wget https://github.com/etcd-io/etcd/releases/download/v3.4.16/etcd-v3.4.16-linux-amd64.tar.gz
tar -xvf etcd-v3.4.16-linux-amd64.tar.gz
cd etcd-v3.4.16-linux-amd64

# 启动etcd(实际生产环境建议用systemd管理)
nohup ./etcd --name etcd1 \
    --data-dir /var/lib/etcd \
    --initial-advertise-peer-urls http://192.168.1.10:2380 \
    --listen-peer-urls http://0.0.0.0:2380 \
    --listen-client-urls http://0.0.0.0:2379 \
    --advertise-client-urls http://192.168.1.10:2379 \
    --initial-cluster "etcd1=http://192.168.1.10:2380,etcd2=http://192.168.1.11:2380,etcd3=http://192.168.1.12:2380" \
    --initial-cluster-state new &

其他节点只需修改--name和IP地址即可。用etcdctl cluster-health验证集群状态。

3. 安装Patroni

Patroni可以通过pip安装:

pip3 install patroni[etcd]

三、配置Patroni管理PostgreSQL

1. 创建Patroni配置文件

以下是一个最小化的/etc/patroni.yml配置:

scope: pgcluster  # 集群名称
namespace: /service/  # etcd中的路径

restapi:
  listen: 0.0.0.0:8008  # Patroni管理API
  connect_address: 192.168.1.10:8008

etcd:
  hosts: "192.168.1.10:2379,192.168.1.11:2379,192.168.1.12:2379"  # etcd集群地址

bootstrap:
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576
    postgresql:
      use_pg_rewind: true
      parameters:
        max_connections: 100
        shared_buffers: 1GB

postgresql:
  listen: 0.0.0.0:5432
  connect_address: 192.168.1.10:5432
  data_dir: /var/lib/pgsql/12/data
  bin_dir: /usr/pgsql-12/bin
  pgpass: /tmp/pgpass
  authentication:
    replication:
      username: replicator
      password: "123456"
    superuser:
      username: postgres
      password: "postgres"

2. 启动Patroni

patroni /etc/patroni.yml

其他节点启动前,记得修改restapi.connect_addresspostgresql.connect_address

四、测试故障转移

1. 查看集群状态

# 通过Patroni API检查
curl http://192.168.1.10:8008/cluster

输出会显示哪个节点是主库(rolemaster)。

2. 模拟主节点宕机

直接kill主节点的Patroni进程:

pkill -f patroni

等待10-30秒后,再次检查集群状态,会发现新的主节点被选举出来。

3. 验证数据同步

在原主节点恢复后,它会自动变成从库并同步新主库的数据:

# 在新主库上创建测试表
psql -h 192.168.1.11 -U postgres -c "CREATE TABLE test_failover(id int);"

# 在原主库上查询该表
psql -h 192.168.1.10 -U postgres -c "\d"
# 应该能看到test_failover表

五、技术细节与注意事项

1. 为什么选择etcd?

etcd比ZooKeeper更轻量,比Consul更适合与Patroni集成。它的watch机制可以实时监控节点状态变化。

2. 网络分区问题

如果etcd集群出现网络分区,可能导致脑裂。建议部署至少3个节点,并配置合理的ttlloop_wait

3. Patroni的监控

可以通过Prometheus抓取Patroni的/metrics端点,监控集群健康状态。

六、总结

Patroni+etcd的组合让PostgreSQL高可用变得非常简单。整个过程自动化,减少了人为操作的风险。当然,生产环境还需要考虑备份、监控等配套措施。如果你正在寻找一个开箱即用的PostgreSQL高可用方案,不妨试试这个组合。