PostgreSQL流复制高可用架构搭建配置实战

PostgreSQL作为功能丰富的开源关系型数据库,其流复制(Streaming Replication)机制是实现数据库高可用架构的核心能力。数据库运维中,主从复制配合自动故障切换工具构建高可用集群,保障数据冗余与服务连续性。本文从流复制原理到Patroni自动切换,完整演示PostgreSQL高可用架构的搭建过程。

PostgreSQL流复制架构原理

PostgreSQL流复制基于WAL(Write-Ahead Log)机制实现。主节点(Primary)将事务日志以WAL记录形式写入,备节点(Standby)通过网络实时接收WAL流并回放,保持与主节点数据一致。流复制的关键进程:

# 流复制核心进程
# Primary端:
#   walsender      - 发送WAL日志给备节点,每个备节点一个
#
# Standby端:
#   walreceiver   - 接收主节点WAL日志
#   startup       - 回放WAL日志恢复数据
#
# 复制模式对比:
# 异步复制   - 主节点提交不等备节点确认,备节点可能有延迟
# 同步复制   - 主节点等待至少一个备节点确认WAL已写入才提交
#
# 备节点类型:
# Hot Standby  - 接收WAL的同时可提供只读查询
# Warm Standby  - 只接收WAL,不接受查询连接

同步复制虽然保障数据零丢失,但会牺牲主节点写入性能(需等待备节点确认)。生产环境通常采用同步+异步混合模式:一个同步备节点保障数据安全,一个异步备节点提供读取扩展。

主节点WAL日志配置

PostgreSQL主节点需要配置WAL相关参数以支持流复制连接:

# postgresql.conf (主节点配置)
# WAL级别: replica支持物理复制,logical支持逻辑复制
wal_level = replica

# WAL发送进程数(等于备节点数量+1)
max_wal_senders = 10

# WAL保留段数,防止备节点断连后需要的WAL被覆盖
wal_keep_size = 1024MB

# WAL写入方式: on(本地fsync), remote_write(备节点写入)
synchronous_commit = on

# 同步复制: 等待备节点确认
synchronous_standby_names = 'FIRST 1 (standby1)'

# 监听所有网卡
listen_addresses = '*'
port = 5432

# 连接数与内存
max_connections = 200
shared_buffers = 4GB
work_mem = 64MB
wal_buffers = 64MB

# 归档配置(用于PITR时间点恢复)
archive_mode = on
archive_command = 'test ! -f /data/pg_archive/%f && cp %p /data/pg_archive/%f'

# pg_hba.conf (允许备节点连接)
# TYPE  DATABASE    USER      ADDRESS         METHOD
host    replication  replica   192.168.10.0/24  md5

配置完成后需要创建专用复制用户并重启服务:

-- 创建复制用户
CREATE ROLE replica WITH REPLICATION LOGIN PASSWORD 'Replica@2026';

-- 查看复制状态
SELECT application_name, client_addr, state, sync_state,
       sent_lsn, write_lsn, flush_lsn, replay_lsn
FROM pg_stat_replication;

-- 查看WAL发送统计
SELECT * FROM pg_stat_wal_receiver;

备节点流复制搭建步骤

使用pg_basebackup工具从主节点克隆基础备份,然后配置为流复制备节点:

# 停止备节点上的PostgreSQL服务
systemctl stop postgresql

# 清空备节点数据目录
rm -rf /var/lib/postgresql/16/main/*

# 从主节点克隆基础备份
pg_basebackup \
  -h 192.168.10.21 \
  -U replica \
  -D /var/lib/postgresql/16/main \
  -Fp -Xs -P -R

# -R 参数自动创建standby.signal文件和primary_conninfo配置
# 生成的postgresql.auto.conf内容:
# primary_conninfo = 'user=replica password=xxx host=192.168.10.21 port=5432'
# primary_slot_name = 'standby1'

# 在主节点创建复制槽(防止WAL被过早回收)
SELECT pg_create_physical_replication_slot('standby1');

# 备节点postgresql.conf额外配置
hot_standby = on
max_standby_streaming_delay = 30s
wal_receiver_status_interval = 1s
hot_standby_feedback = on

# 启动备节点
systemctl start postgresql

# 验证备节点状态
psql -c "SELECT pg_is_in_recovery();"  -- 返回true表示备节点
psql -c "SELECT * FROM pg_stat_wal_receiver();"  -- 查看接收状态

复制槽(Replication Slot)的作用是确保主节点不会在备节点断连期间回收所需的WAL段文件。不使用复制槽时,如果备节点长时间断连,主节点可能回收WAL导致备节点无法继续复制。启用hot_standby_feedback参数可防止主节点执行VACUUM时清理备节点正在使用的行,避免备节点查询冲突。

Patroni自动故障切换部署

Patroni是PostgreSQL高可用管理工具,自动监控主节点状态并在故障时触发切换。配合etcd作为配置存储中心实现集群协调:

# 安装etcd集群(3节点)
apt install etcd -y

# etcd配置 /etc/etcd/etcd.conf (node1)
ETCD_NAME=node1
ETCD_DATA_DIR=/var/lib/etcd
ETCD_LISTEN_PEER_URLS=http://192.168.10.21:2380
ETCD_LISTEN_CLIENT_URLS=http://192.168.10.21:2379
ETCD_INITIAL_CLUSTER=node1=http://192.168.10.21:2380,node2=http://192.168.10.22:2380,node3=http://192.168.10.23:2380
ETCD_INITIAL_CLUSTER_TOKEN=pg-cluster
ETCD_INITIAL_ADVERTISE_PEER_URLS=http://192.168.10.21:2380

# 安装Patroni
pip3 install patroni[etcd]

# Patroni配置 /etc/patroni/patroni.yml (node1)
scope: pg-cluster
name: node1

restapi:
  listen: 0.0.0.0:8008
  connect_address: 192.168.10.21:8008

etcd:
  hosts: 192.168.10.21:2379,192.168.10.22:2379,192.168.10.23:2379

bootstrap:
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576
    synchronous_mode: true
    postgresql:
      use_pg_rewind: true
      parameters:
        wal_level: replica
        max_wal_senders: 10
        wal_keep_size: 1024MB

  initdb:
  - encoding: UTF8
  - data-checksums

postgresql:
  listen: 0.0.0.0:5432
  connect_address: 192.168.10.21:5432
  data_dir: /var/lib/postgresql/16/main
  bin_dir: /usr/lib/postgresql/16/bin
  authentication:
    replication:
      username: replica
      password: Replica@2026
    superuser:
      username: postgres
      password: PgAdmin@2026
  parameters:
    hot_standby: on
    max_connections: 200

tags:
    nofailover: false
    noloadbalance: false
    clonefrom: false

# 启动Patroni服务
systemctl start patroni

# 查看集群状态
patronictl -c /etc/patroni/patroni.yml list
# + Cluster: pg-cluster --+---------+----+-----------+
# | Member | Host        | Role    | State    | Lag in MB |
# +--------+-------------+---------+----------+----------+
# | node1  | 192.168.10.21| Leader  | running  |          |
# | node2  | 192.168.10.22| Replica | streaming| 0        |
# | node3  | 192.168.10.23| Replica | streaming| 0        |
# +--------+-------------+---------+----------+----------+

当主节点故障时,Patroni在10秒(loop_wait)内检测到,通过etcd进行Leader选举,将延迟最小的备节点提升为新的主节点。切换过程中synchronous_mode参数保证新主节点的数据与原主节点一致,避免数据丢失。故障节点恢复后,Patroni自动通过pg_rewind同步增量日志重新加入集群。

PgBouncer连接池配置与读写分离

高可用集群需要配合连接池实现读写分离,PgBouncer是PostgreSQL最常用的连接池中间件:

# 安装PgBouncer
apt install pgbouncer -y

# PgBouncer配置 /etc/pgbouncer/pgbouncer.ini
[databases]
; 写请求路由到主节点
primary = host=192.168.10.21 port=5432 dbname=appdb
; 读请求路由到备节点
replica = host=192.168.10.22 port=5432 dbname=appdb
; 通过Patroni REST API自动路由到当前主节点
; 需配合pgbouncer的USE_PATRONI功能

[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 6432
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
pool_mode = transaction
max_client_conn = 500
default_pool_size = 20
reserve_pool_size = 5
reserve_pool_timeout = 3
server_idle_timeout = 60
query_timeout = 30
query_wait_timeout = 30

# 应用层读写分离配置(Java示例)
# 写操作: jdbc:postgresql://pgbouncer:6432/primary
# 读操作: jdbc:postgresql://pgbouncer:6432/replica

pool_mode设置为transaction级别时,PgBouncer在事务级别复用后端连接,平衡了连接利用率和事务隔离性。配合Patroni的REST API(/read-write端点),PgBouncer可以动态感知主节点切换并自动重连新主节点,实现故障切换对应用透明。数据库高可用架构的搭建需要综合考虑数据复制延迟、故障检测灵敏度与切换后的数据一致性,Patroni+etcd+PgBouncer组合是目前PostgreSQL生产环境的主流高可用方案。

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

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

相关推荐