PostgreSQL流复制配置与Patroni高可用集群搭建实战

PostgreSQL流复制(Streaming Replication)是构建数据库高可用架构的基础机制,Patroni在此基础上提供了自动故障检测、主从切换和集群管理的完整方案。在金融、电商等对数据一致性和可用性要求严苛的场景中,Patroni+etcd+HAProxy的组合已成为PostgreSQL高可用的标准实践。本文从流复制的基础配置入手,逐步搭建三节点的Patroni高可用集群,并覆盖故障切换验证和日常运维操作。

PostgreSQL流复制原理与WAL日志传输机制

PostgreSQL通过WAL(Write-Ahead Logging)机制实现流复制。主节点(Primary)将事务日志写入WAL文件后,通过TCP连接将WAL数据流式传输到备节点(Standby),备节点实时重放WAL日志保持数据同步。

-- 主节点配置 (postgresql.conf)
wal_level = replica
max_wal_senders = 10
wal_keep_size = 1024        # 保留1GB WAL日志,避免备节点断连后需要全量重传
hot_standby = on            # (备节点配置)允许只读查询

-- 创建复制专用用户
CREATE ROLE repl WITH REPLICATION LOGIN PASSWORD 'repl_secure_pass';

-- pg_hba.conf 添加复制权限
# host  replication  repl  192.168.1.0/24  md5

wal_level=replica是流复制的最低要求,logical级别还支持逻辑解码。max_wal_senders控制同时连接的备节点数量。wal_keep_size(PostgreSQL 13+替代了wal_keep_segments)指定保留的WAL文件大小,太大会浪费磁盘,太小可能导致备节点断连后无法增量同步而触发全量基础备份。

基础备份与备节点初始化操作流程

备节点的初始化通过pg_basebackup工具从主节点拉取完整数据快照,然后配置为流复制模式启动。

# 在备节点执行基础备份
pg_basebackup \
  -h 192.168.1.10 \
  -U repl \
  -D /var/lib/postgresql/data \
  -Fp \
  -Xs \
  -P \
  -R

# -Fp: 以plain格式输出
# -Xs: 使用stream方式传输WAL(与基础备份并行)
# -P: 显示进度
# -R: 自动创建standby.signal文件和连接配置

-R参数会自动在数据目录中创建standby.signal文件(PostgreSQL 12+支持),并写入primary_conninfo连接信息到postgresql.auto.conf。备节点启动后自动进入恢复模式,通过primary_conninfo配置的连接信息从主节点接收WAL流。

# postgresql.auto.conf 自动生成的内容
primary_conninfo = 'user=repl password=repl_secure_pass host=192.168.1.10 port=5432 sslmode=prefer'
primary_slot_name = 'standby_slot'

复制槽管理与WAL积压监控方法

复制槽(Replication Slot)确保主节点不会在备节点收到WAL之前删除对应的WAL文件。未使用复制槽时,如果备节点断连时间较长,主节点可能已循环覆盖WAL文件,导致备节点无法增量恢复。但复制槽也有风险:备节点长期断连时,WAL文件无限堆积导致主节点磁盘占满。

-- 创建物理复制槽
SELECT pg_create_physical_replication_slot('standby_slot');

-- 查看复制槽状态
SELECT slot_name, active, restart_lsn,
       pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) AS lag_bytes
FROM pg_replication_slots;

-- 查看复制连接和延迟
SELECT application_name, state, sync_state,
       sent_lsn, write_lsn, flush_lsn, replay_lsn,
       pg_wal_lsn_diff(sent_lsn, replay_lsn) AS replay_lag_bytes
FROM pg_stat_replication;

sync_state字段显示同步模式:async表示异步复制(备节点不影响主节点提交),sync表示同步复制(主节点等待至少一个同步备节点确认写入后才提交)。replay_lag_bytes显示备节点重放延迟的字节数,如果持续增长说明备节点处理速度跟不上主节点。

Patroni集群架构设计与etcd配置

Patroni是Zalando开源的PostgreSQL高可用管理工具,依赖etcd/Consul/ZooKeeper作为分布式配置存储实现Leader选举和状态同步。

# etcd配置 (三节点集群,每个节点一个实例)
# /etc/etcd/etcd.conf
name: 'etcd-node1'
data-dir: '/var/lib/etcd'
listen-peer-urls: 'http://192.168.1.10:2380'
listen-client-urls: 'http://192.168.1.10:2379'
initial-cluster: 'etcd-node1=http://192.168.1.10:2380,etcd-node2=http://192.168.1.11:2380,etcd-node3=http://192.168.1.12:2380'
initial-cluster-state: 'new'
initial-cluster-token: 'pg-ha-cluster'

etcd集群部署在PostgreSQL节点相同或独立的服务器上。三节点etcd能容忍单节点故障。Patroni使用etcd的分布式锁机制实现Leader选举:最先获取到锁的节点成为Primary,其余节点自动配置为Standby并连接到当前Primary。

Patroni YAML配置文件详解与调优参数

# /etc/patroni/patroni.yml (节点1)
scope: pg-ha-cluster
name: pg-node1

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

etcd:
  hosts: 192.168.1.10:2379,192.168.1.11:2379,192.168.1.12:2379

bootstrap:
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576   # 1MB,超过则不允许切换
    maximum_lag_on_sync: 1048576
    synchronous_mode: true              # 开启同步复制
    synchronous_mode_strict: false      # 允许在仅有异步备节点时降级运行
    postgresql:
      use_pg_rewind: true               # 允许使用pg_rewind修复时间线分叉
      parameters:
        wal_level: replica
        max_wal_senders: 10
        wal_keep_size: 1024
        hot_standby: on
        synchronous_commit: on
        synchronous_standby_names: '*'

  initdb:
    - encoding: UTF8
    - data-checksums

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: repl
      password: repl_secure_pass
    superuser:
      username: postgres
      password: pg_secure_pass
  pg_hba:
    - host replication repl 192.168.1.0/24 md5
    - host all all 0.0.0.0/0 md5

tags:
  nofailover: false
  noloadbalance: false
  clonefrom: false

ttl=30是Leader租约时长,Patroni每loop_wait=10秒续约一次。如果Primary节点宕机,最多retry_timeout=10秒后etcd租约过期,触发重新选举。maximum_lag_on_failover=1048576(1MB)是安全阈值:备节点延迟超过1MB时不允许提升为Primary,防止数据丢失。synchronous_mode=true要求至少一个同步备节点确认写入后主节点才返回提交成功。

自动故障切换流程与手动运维操作指南

Patroni通过REST API提供集群管理接口,patronictl命令行工具封装了常用操作。

# 查看集群状态
patronictl -c /etc/patroni/patroni.yml list

# 输出示例
# + Cluster: pg-ha-cluster ----+---------+----+-----------+
# | Member    | Host           | Role    | State    | TL | Lag in MB |
# | pg-node1  | 192.168.1.10   | Leader  | running  | 5  |           |
# | pg-node2  | 192.168.1.11   | Replica | streaming| 5  |         0 |
# | pg-node3  | 192.168.1.12   | Replica | streaming| 5  |         0 |
# +-----------+----------------+---------+----------+----+-----------+

# 手动切换主节点(计划性维护)
patronictl switchover -c /etc/patroni/patroni.yml \
  --master pg-node1 --candidate pg-node2

# 重新初始化故障节点(数据损坏后修复)
patronictl reinit -c /etc/patroni/patroni.yml pg-ha-cluster pg-node3

# 暂停自动故障切换(运维窗口期)
patronictl pause -c /etc/patroni/patroni.yml

# 恢复自动故障切换
patronictl resume -c /etc/patroni/patroni.yml

switchover是计划性切换,先验证候选节点的复制延迟为零,然后优雅降级当前Leader、提升候选节点为新Leader,整个过程在数秒内完成。failover是非计划性的:Leader节点不可用时自动触发,Patroni在各Standby中选择延迟最小的节点提升为Leader。已宕机的原Leader恢复后,Patroni通过pg_rewind合并时间线分叉,将其重新接入集群为Standby。

HAProxy配置读写分离路由:

frontend pg_read_write
    bind *:5432
    mode tcp
    use_backend pg_primary

frontend pg_read_only
    bind *:5433
    mode tcp
    use_backend pg_standby

backend pg_primary
    mode tcp
    option tcp-check
    # Patroni REST API健康检查:只有Leader返回200
    tcp-check connect port 8008
    tcp-check send GET\ /primary\ HTTP/1.1\r\n\r\n
    tcp-check expect string 200
    server pg-node1 192.168.1.10:5432 check
    server pg-node2 192.168.1.11:5432 check
    server pg-node3 192.168.1.12:5432 check

backend pg_standby
    mode tcp
    option tcp-check
    tcp-check connect port 8008
    tcp-check send GET\ /replica\ HTTP/1.1\r\n\r\n
    tcp-check expect string 200
    server pg-node1 192.168.1.10:5432 check
    server pg-node2 192.168.1.11:5432 check
    server pg-node3 192.168.1.12:5432 check

5432端口路由到Primary节点,5433端口号路由到Standby节点进行读负载均衡。Patroni的/primary接口只在Leader节点返回200,/replica接口只在Standby节点返回200,HAProxy据此自动识别角色变化。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/postgresql-liu-fu-zhi-pei-zhi-yu-patroni-gao-ke-yong-ji-qun/

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

相关推荐