PostgreSQL高可用架构搭建实战:流复制与Patroni自动故障转移

PostgreSQL高可用架构通过流复制和自动故障转移机制,在主库故障时实现秒级切换到备库,是数据库运维中保障数据可靠性和服务连续性的核心方案。Patroni作为PostgreSQL高可用管理工具,配合etcd实现集群协调,已成为PostgreSQL生产部署的事实标准。

PostgreSQL流复制原理与配置

PostgreSQL流复制(Streaming Replication)基于WAL(Write-Ahead Log)机制,主库将WAL日志实时传输到备库,备库重放日志保持数据同步。配置流复制需要修改主库postgresql.conf和pg_hba.conf:

# 主库 postgresql.conf
wal_level = replica
max_wal_senders = 10
wal_keep_size = 1024          # 保留1GB WAL日志,避免备库断连后需要全量同步
hot_standby = on
synchronous_commit = on      # 同步提交,确保数据零丢失

# 主库 pg_hba.conf - 允许备库连接
host replication replicator 192.168.1.0/24 md5

# 创建复制用户
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'secure_pwd';

# 备库使用pg_basebackup初始化
pg_basebackup -h 192.168.1.10 -U replicator -D /var/lib/postgresql/data \
    -Fp -Xs -P -R
# -R 自动创建standby.signal和primary_conninfo配置

# 备库 postgresql.auto.conf
primary_conninfo = 'host=192.168.1.10 port=5432 user=replicator password=secure_pwd'
hot_standby = on
hot_standby_feedback = on    # 防止备库长查询被主库vacuum中断

流复制有异步和同步两种模式。异步复制(默认)主库提交不等备库确认,性能高但可能丢失少量最新数据。同步复制主库等待至少一个备库确认收到WAL后才提交,保证数据零丢失,但会增加写入延迟。生产环境建议采用同步复制配合本地异步复制的多级架构。

Patroni集群部署与协调配置

Patroni管理PostgreSQL集群的生命周期,通过etcd(或Consul/ZooKeeper)存储集群元数据和进行Leader选举。每个PostgreSQL节点运行一个Patroni进程:

# patroni.yml (node-1)
scope: pg-cluster
name: node-1

restapi:
  listen: 0.0.0.0:8008
  connect_address: 192.168.1.10:8008

etcd:
  hosts: 192.168.1.20:2379,192.168.1.21:2379,192.168.1.22:2379

bootstrap:
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 20
    maximum_lag_on_failover: 1048576  # 1MB,超过此延迟不允许故障转移
    synchronous_mode: true
    postgresql:
      parameters:
        wal_level: replica
        max_wal_senders: 10
        wal_keep_size: 1024
        hot_standby: on
        synchronous_commit: on

postgresql:
  listen: 0.0.0.0:5432
  connect_address: 192.168.1.10:5432
  data_dir: /var/lib/postgresql/data
  bin_dir: /usr/lib/postgresql/15/bin
  authentication:
    replication:
      username: replicator
      password: secure_pwd
    superuser:
      username: postgres
      password: super_secure_pwd

tags:
    nofailover: false
    noloadbalance: false
    clonefrom: false
    sync_standby: true  # 标记为同步备库候选

Patroni的关键参数:ttl=30表示Leader租约30秒,超时未续约触发选举;loop_wait=10表示每10秒检查一次集群状态;maximum_lag_on_failover限制故障转移时备库最大允许的复制延迟,防止切换到数据落后的节点。

自动故障转移流程与选举机制

当主库故障时,Patroni的故障转移流程如下:

  1. 主库Patroni停止心跳,etcd中Leader租约过期(30秒后)
  2. 备库Patroni检测到Leader丢失,发起选举
  3. 选举获胜条件:WAL接收位置最靠前、且复制延迟在maximum_lag_on_failover范围内
  4. 新Leader执行promote提升为主库,更新etcd中的Leader信息
  5. 其他备库自动指向新主库,重新建立流复制连接
# 查看集群状态
patronictl list
# +---------+--------+------------+----+-----------+
# | Member  | Host   | Role       | TL | Lag in MB |
# +---------+--------+------------+----+-----------+
# | node-1  | 10.0.1.10 | Leader    | 15 |          |
# | node-2  | 10.0.1.11 | Replica   | 15 | 0        |
# | node-3  | 10.0.1.12 | Sync      | 15 | 0        |
# +---------+--------+------------+----+-----------+

# 手动切换(维护场景)
patronictl switchover pg-cluster
# 确认后Patroni将当前Leader降级为Replica,提升指定备库为新Leader

# 查看集群配置
patronictl show-config pg-cluster

同步模式下,Patroni确保始终有一个同步备库(Sync角色),只有同步备库才有资格在故障转移时成为新Leader,保证数据零丢失。但同步模式下如果同步备库也宕机,主库会降级为异步模式继续运行(取决于synchronous_mode_strict设置)。

HAProxy负载均衡与读写分离

Patroni提供REST API用于健康检查,结合HAProxy实现读写分离。应用写请求到主库,读请求分发到备库:

# haproxy.cfg
frontend pg_write
    bind *:5432
    default_backend pg_master

frontend pg_read
    bind *:5433
    default_backend pg_replicas

backend pg_master
    option httpchk
    http-check expect status 200
    default-server inter 3s fall 3 rise 2
    server node-1 192.168.1.10:5432 check port 8008
    server node-2 192.168.1.11:5432 check port 8008
    server node-3 192.168.1.12:5432 check port 8008
    # Patroni返回200表示Leader,503表示非Leader
    # HAProxy只会将请求路由到返回200的节点

backend pg_replicas
    balance roundrobin
    option httpchk
    http-check expect status 200
    default-server inter 3s fall 3 rise 2
    server node-1 192.168.1.10:5432 check port 8008
    server node-2 192.168.1.11:5432 check port 8008
    server node-3 192.168.1.12:5432 check port 8008
    # 需要配置Patroni返回200给Replica角色
    # 在Patroni的restapi中配置: 
    #   standby_cluster: null (Leader返回200)
    #   或使用tags: nofailover: true (非Leader也返回200)

HAProxy通过Patroni的8008端口健康检查接口判断节点角色。Leader节点返回HTTP 200,Replica节点返回HTTP 503(默认)。写端口5432只会路由到Leader,读端口5433通过roundrobin分发到所有Replica。故障转移时,HAProxy自动检测到新Leader并切换写流量,整个切换过程对应用透明。

集群监控与日常运维要点

PostgreSQL高可用集群的监控指标包括:复制延迟(pg_stat_replication中的sent_lsn/replay_lsn差值)、连接数(pg_stat_activity)、WAL生成速率、缓存命中率、慢查询。使用Prometheus + postgres_exporter采集指标:

# postgres_exporter配置
DATA_SOURCE_NAME="postgresql://monitor:monitor_pwd@localhost:5432/postgres?sslmode=disable"

# 关键PromQL查询
# 复制延迟(字节)
pg_replication_lag_bytes = pg_stat_replication_pg_wal_lsn - pg_stat_replication_pg_replay_lsn

# 复制延迟(秒)
pg_replication_lag_seconds = time() - pg_stat_replication_pg_replay_timestamp

# 连接数使用率
pg_connections_ratio = pg_stat_activity_count / pg_settings_max_connections

日常运维中需要定期验证故障转移功能。在维护窗口执行patronictl switchover测试主备切换是否正常,检查应用连接是否自动恢复。WAL归档配置(archive_mode=on + archive_command)确保WAL日志持久化到对象存储,用于时间点恢复(PITR)。定期执行pg_dump逻辑备份作为物理复制的补充,防止逻辑损坏(如误删表)导致数据丢失。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/postgresql-gao-ke-yong-jia-gou-da-jian-shi-zhan-liu-fu-zhi/

(0)
小编小编
上一篇 5小时前
下一篇 5小时前

相关推荐