Skip to content

PostgreSQL 流式复制环境部署与配置

流式复制是 PostgreSQL 高可用架构的核心基础,通过实时传输 WAL(Write-Ahead Logging)日志实现主从数据同步。对于生产环境而言,掌握流式复制的部署、配置和管理是构建高可用 PostgreSQL 集群的关键技能。

流式复制概述

什么是流式复制

流式复制是 PostgreSQL 9.0 引入的主从复制机制,通过 TCP/IP 连接将主库生成的 WAL 日志实时流传输到从库。从库接收到 WAL 日志后,立即写入本地 WAL 文件并异步应用,实现近实时的数据同步,通常延迟在毫秒级别。

流式复制的类型

  • 异步复制:主库提交事务时不等待从库确认,性能最优但在主库故障时可能丢失数据
  • 同步复制:主库必须等待至少一个从库确认 WAL 写入磁盘后才能提交事务,确保数据一致性但会降低主库写入性能
  • 半同步复制:主库等待从库确认 WAL 接收(不一定写入磁盘),在性能和一致性之间取得平衡

流式复制的核心优势

  • 高实时性:主从数据延迟通常在毫秒级别
  • 数据可靠性:基于 WAL 日志确保数据一致性
  • 部署灵活性:支持多种复制模式和拓扑结构
  • 读写分离:从库支持只读查询,实现负载均衡
  • 故障恢复:作为高可用架构的基础,支持快速故障转移
  • 升级平滑:支持主从版本滚动升级
  • 备份安全:从库备份不影响主库性能

环境准备

生产环境硬件要求

组件一般业务配置高并发业务配置超大流量业务配置
CPU4 核8-16 核16-32 核
内存16 GB32-64 GB128 GB+
存储200 GB NVMe SSD500 GB NVMe SSD1 TB+ NVMe SSD
网络万兆以太网万兆以太网25/100 千兆以太网
IOPS10,000+50,000+100,000+

软件要求

软件版本要求生产建议
PostgreSQL13 或以上推荐 PostgreSQL 15-16,获得更好的性能和新特性支持
操作系统RHEL/CentOS 8+, Ubuntu 20.04+, Debian 11+推荐 RHEL 9 或 Ubuntu 22.04 LTS
内核版本Linux 4.18+推荐 Linux 5.10+,支持更多性能优化

节点规划示例

本示例部署 1 主 2 从的流式复制集群,适合大多数生产场景:

节点角色主机名IP 地址复制模式用途
主库pg-master192.168.1.10主库处理所有写入请求
从库 1pg-slave1192.168.1.11同步复制高可用备用,确保数据一致性
从库 2pg-slave2192.168.1.12异步复制读写分离,承担只读查询

操作系统预配置

在所有节点上执行以下预配置,确保 PostgreSQL 运行环境符合生产要求:

bash
# 关闭 SELinux(或配置正确的策略)
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
setenforce 0

# 关闭防火墙(或配置适当规则)
systemctl stop firewalld
systemctl disable firewalld

# 配置内核参数
cat >> /etc/sysctl.conf <<EOF
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 4096
vm.swappiness = 10
vm.overcommit_memory = 2
vm.overcommit_ratio = 90
EOF
sysctl -p

# 配置系统资源限制
cat >> /etc/security/limits.d/postgres.conf <<EOF
postgres soft nofile 65536
postgres hard nofile 65536
postgres soft nproc 65536
postgres hard nproc 65536
EOF

# 安装必要依赖
yum install -y epel-release
# RHEL/CentOS
yum install -y wget curl openssl-devel libselinux-devel libxml2-devel libxslt-devel zlib-devel
# Ubuntu/Debian
sudo apt-get install -y wget curl libssl-dev libxml2-dev libxslt1-dev zlib1g-dev

主库配置

1. 安装 PostgreSQL

在 CentOS/RHEL 上安装

bash
# 在所有节点上执行
yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm
yum install -y postgresql15 postgresql15-server postgresql15-contrib

在 Ubuntu/Debian 上安装

bash
# 在所有节点上执行
sudo apt-get update
sudo apt-get install -y gnupg2 wget
echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt-get update
sudo apt-get install -y postgresql-15 postgresql-15-contrib

2. 初始化主库

bash
# 在主库上执行
/usr/pgsql-15/bin/postgresql-15-setup initdb
systemctl start postgresql-15
systemctl enable postgresql-15

3. 配置主库参数

编辑 /var/lib/pgsql/15/data/postgresql.conf 文件,以下是生产环境推荐配置:

ini
# 基本配置
listen_addresses = '*'  # 允许所有 IP 访问
port = 5432  # PostgreSQL 服务端口

# 资源配置
max_connections = 200  # 最大连接数,根据业务调整
shared_buffers = 4GB  # 共享内存缓冲区,建议为系统内存的 25%
work_mem = 4MB  # 每个工作进程的内存
maintenance_work_mem = 1GB  # 维护操作的内存

# WAL 配置(核心复制相关)
wal_level = replica  # 复制级别,支持物理复制
archive_mode = on  # 启用 WAL 归档
archive_command = 'rsync -a %p postgres@backup-server:/backup/wal/%f'  # 使用 rsync 归档到备份服务器
archive_timeout = 60  # 每 60 秒强制归档一次 WAL 文件
max_wal_senders = 20  # 最大 WAL 发送进程数,建议比从库数量多 5
max_replication_slots = 20  # 最大复制槽数量
wal_keep_size = 16GB  # 保留的 WAL 日志大小,PostgreSQL 13+ 推荐设置
wal_compression = on  # 压缩 WAL 日志,PostgreSQL 14+ 支持

# 同步复制配置
synchronous_commit = remote_write  # 半同步模式,平衡性能和一致性
# 配置同步从库,FIRST 1 表示第一个同步确认的从库
synchronous_standby_names = 'FIRST 1 (pg-slave1, pg-slave2)'  # 使用主机名匹配

# 其他复制相关配置
hot_standby_feedback = on  # 防止主库清理从库正在使用的旧数据
max_wal_size = 16GB  # 最大 WAL 文件大小
min_wal_size = 4GB  # 最小 WAL 文件大小

# 性能优化
checkpoint_completion_target = 0.9  #  checkpoint 完成目标比例
random_page_cost = 1.1  # SSD 存储建议设置为 1.1
effective_io_concurrency = 200  # SSD 存储建议设置为 200

4. 配置主库认证

编辑 /var/lib/pgsql/15/data/pg_hba.conf 文件,以下是生产环境安全配置:

# 本地连接配置
local   all             postgres                                peer
local   all             all                                     peer

host    all             all             127.0.0.1/32            scram-sha-256
host    all             all             ::1/128                 scram-sha-256

# 复制用户配置(仅允许从库 IP 访问)
host    replication     replicator      192.168.1.0/24          scram-sha-256  # 仅允许从库网段访问

# 应用用户配置(根据业务需求调整)
host    appdb           appuser         10.0.0.0/8              scram-sha-256  # 应用服务器网段

安全最佳实践

  • 使用 scram-sha-256 替代 md5 进行密码认证
  • 严格限制复制用户的访问网段,避免使用 0.0.0.0/0
  • 为不同用户分配不同的数据库权限
  • 定期轮换密码
  • 考虑使用证书认证(SSL/TLS)增强安全性

5. 创建复制用户

bash
# 在主库上执行
sudo -u postgres psql -c "CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'rep-pass';"

6. 创建 WAL 归档目录

bash
# 在主库上执行
mkdir -p /var/lib/pgsql/15/archive
chown -R postgres:postgres /var/lib/pgsql/15/archive

7. 重启主库

bash
# 在主库上执行
systemctl restart postgresql-15

从库配置

1. 从主库克隆数据

使用 pg_basebackup 从主库克隆初始数据,这是设置从库的基础步骤:

bash
# 在从库上执行
# 停止 PostgreSQL 服务(如果已启动)
systemctl stop postgresql-15

# 清空数据目录(如果已初始化)
rm -rf /var/lib/pgsql/15/data/*

# 从主库克隆数据(生产环境推荐配置)
sudo -u postgres pg_basebackup \
  -h pg-master \
  -U replicator \
  -D /var/lib/pgsql/15/data \
  -Fp \
  -Xs \
  -Pv \
  -R \
  --checkpoint=fast \
  --wal-method=stream

参数详解

  • -h:主库主机名或 IP 地址
  • -U:复制用户
  • -D:从库数据目录
  • -Fp:使用纯文本格式备份
  • -Xs:流式复制模式传输 WAL 日志
  • -Pv:显示进度和详细信息
  • -R:自动生成复制配置文件
  • --checkpoint=fast:执行快速检查点,减少主库阻塞时间
  • --wal-method=stream:使用流式 WAL 传输,确保数据一致性

2. 配置从库参数

编辑 /var/lib/pgsql/15/data/postgresql.conf 文件,以下是生产环境推荐配置:

ini
# 基本配置
listen_addresses = '*'  # 允许所有 IP 访问
port = 5432  # PostgreSQL 服务端口

# 资源配置(与主库保持一致或适当调整)
max_connections = 300  # 从库可接受更多连接用于只读查询
shared_buffers = 4GB
work_mem = 4MB
maintenance_work_mem = 1GB

# 从库核心配置
hot_standby = on  # 允许从库提供只读查询服务
max_standby_streaming_delay = 60s  # 从库应用 WAL 日志的最大延迟
wal_receiver_timeout = 60s  # WAL 接收器超时时间
hot_standby_feedback = on  # 防止主库清理从库正在使用的旧数据
wal_receiver_status_interval = 10s  # 从库向主库报告状态的时间间隔
recovery_min_apply_delay = 0s  # 延迟复制(可用于时间点恢复)

# 日志配置
log_replication_commands = on  # 记录复制相关命令
log_min_duration_statement = 5000  # 记录执行时间超过 5 秒的语句
log_checkpoints = on  # 记录检查点信息

# 性能优化
random_page_cost = 1.1  # SSD 存储建议设置
effective_io_concurrency = 200  # SSD 存储建议设置
max_parallel_workers_per_gather = 4  # 并行查询配置
max_parallel_workers = 8  # 并行工作进程数

3. 验证和优化复制配置

检查 pg_basebackup 自动生成的复制配置:

bash
# 在从库上执行
cat /var/lib/pgsql/15/data/postgresql.auto.conf

预期输出:

# Do not edit this file manually!
# It will be overwritten by the ALTER SYSTEM command.
primary_conninfo = 'user=replicator password=rep-pass host=pg-master port=5432 sslmode=prefer sslcompression=0 gssencmode=prefer krbsrvname=postgres target_session_attrs=any'
primary_slot_name = 'pg_basebackup_12345678'

优化建议

  • 根据从库角色修改 primary_slot_name,例如 slave1_slot
  • 配置 sslmode=verify-full 启用 SSL 加密连接
  • 添加 application_name 参数标识从库身份

4. 启动并验证从库

bash
# 在从库上执行
systemctl start postgresql-15
systemctl enable postgresql-15

# 验证从库状态
sudo -u postgres psql -c "SELECT pg_is_in_recovery(), pg_last_wal_replay_lsn();"

预期输出:

 pg_is_in_recovery | pg_last_wal_replay_lsn 
------------------+------------------------
 t                | 0/3000148

验证复制状态

1. 主库复制状态检查

在主库上执行以下查询,全面了解复制状态:

sql
-- 在主库上执行
SELECT 
    application_name,  -- 从库应用名称
    state,             -- 复制状态(streaming表示正常)
    sent_lsn,          -- 主库已发送的 WAL 位置
    write_lsn,         -- 从库已写入的 WAL 位置
    flush_lsn,         -- 从库已刷新到磁盘的 WAL 位置
    replay_lsn,        -- 从库已应用的 WAL 位置
    sync_state,        -- 同步状态(async/sync/quorum)
    write_lag,         -- 主库到从库写入延迟
    flush_lag,         -- 主库到从库刷新延迟
    replay_lag,        -- 主库到从库应用延迟
    client_addr        -- 从库 IP 地址
FROM pg_stat_replication;

状态解读

  • statestreaming 表示复制正常
  • sync_statesync 表示同步复制,async 表示异步复制
  • write_lag/flush_lag/replay_lag:PostgreSQL 14+ 新增,直接显示延迟时间

2. 从库复制状态检查

在从库上执行以下查询,验证从库状态:

sql
-- 在从库上执行
SELECT 
    pg_is_in_recovery() AS is_replica,              -- 是否为从库
    pg_last_wal_receive_lsn() AS received_lsn,     -- 已接收的 WAL 位置
    pg_last_wal_replay_lsn() AS replayed_lsn,      -- 已应用的 WAL 位置
    now() - pg_last_xact_replay_timestamp() AS replication_delay,  -- 复制延迟
    pg_wal_lsn_diff(pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn()) AS lsn_diff_bytes  -- 接收与应用的 LSN 差异
FROM dual;

-- 查看从库 WAL 接收器状态
SELECT 
    status,          -- WAL 接收器状态
    receive_start_lsn, -- 开始接收的 WAL 位置
    latest_end_lsn,   -- 最新接收的 WAL 位置
    slot_name,        -- 使用的复制槽名称
    sender_host,      -- 主库主机名
    sender_port       -- 主库端口
FROM pg_stat_wal_receiver;

3. 复制槽状态检查

在主库上检查复制槽状态,确保没有无效复制槽导致 WAL 堆积:

sql
-- 在主库上执行
SELECT 
    slot_name,        -- 复制槽名称
    slot_type,        -- 复制槽类型(physical/logical)
    active,           -- 是否活跃
    pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) AS lag_bytes,  -- 复制延迟字节数
    active_pid        -- 活跃进程 ID
FROM pg_replication_slots;

4. 数据同步测试

在主库上创建测试表并插入数据,验证从库是否正确同步:

sql
-- 在主库上执行
CREATE TABLE test_replication (
    id serial primary key,
    data text,
    created_at timestamp default current_timestamp
);

-- 插入测试数据
INSERT INTO test_replication (data) VALUES ('test data from master'), ('another test');

-- 查看主库数据
SELECT * FROM test_replication;

在从库上验证数据同步:

sql
-- 在从库上执行
SELECT * FROM test_replication;

5. 实时复制监控

使用以下命令实时监控复制状态:

bash
# 主库:每秒监控复制状态
watch -n 1 "psql -c 'SELECT application_name, state, sync_state, write_lag, flush_lag, replay_lag FROM pg_stat_replication;'"

# 从库:每秒监控复制延迟
watch -n 1 "psql -c 'SELECT now() - pg_last_xact_replay_timestamp() AS delay;'"

流式复制高级配置

1. 复制槽配置与管理

复制槽是 PostgreSQL 10 引入的重要功能,用于防止主库过早删除从库尚未接收的 WAL 日志,确保从库在断开连接后重新连接时能够继续复制,不会因 WAL 日志丢失而需要重新初始化。

创建物理复制槽

在主库上为每个从库创建独立的复制槽:

sql
-- 在主库上执行
-- 为 pg-slave1 创建复制槽
SELECT * FROM pg_create_physical_replication_slot('pg_slave1_slot');

-- 为 pg-slave2 创建复制槽  
SELECT * FROM pg_create_physical_replication_slot('pg_slave2_slot');

-- 使用 WITH WAL 选项确保复制槽立即开始保留 WAL
SELECT * FROM pg_create_physical_replication_slot('pg_slave3_slot', true);

配置从库使用复制槽

编辑从库的 postgresql.auto.conf 文件,添加或修改复制槽配置:

ini
# 在 pg-slave1 上配置
primary_slot_name = 'pg_slave1_slot'

# 在 pg-slave2 上配置
primary_slot_name = 'pg_slave2_slot'

或者在使用 pg_basebackup 初始化从库时,通过 --slot 参数指定复制槽:

bash
sudo -u postgres pg_basebackup \
  -h pg-master \
  -U replicator \
  -D /var/lib/pgsql/15/data \
  -Fp -Xs -Pv -R \
  --slot=pg_slave1_slot

复制槽监控与管理

监控复制槽状态

sql
-- 在主库上执行
SELECT 
    slot_name,
    slot_type,
    active,
    active_pid,
    pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) AS lag_bytes,
    pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS lag_size,
    pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn) AS flush_diff_bytes
FROM pg_replication_slots;

删除无效复制槽

sql
-- 在主库上执行
-- 删除不活跃且延迟较大的复制槽
SELECT pg_drop_replication_slot('unused_slot');

复制槽最佳实践

  1. 每个从库一个复制槽:避免多个从库共享同一复制槽
  2. 定期清理无效复制槽:防止 WAL 日志堆积导致磁盘空间不足
  3. 监控复制槽延迟:设置告警阈值,当延迟超过阈值时及时处理
  4. 结合 wal_keep_size 使用:复制槽与 wal_keep_size 结合使用,提供双重保障
  5. 使用逻辑复制槽注意事项:逻辑复制槽会保留更多 WAL 日志,需要更严格的监控

2. 半同步复制配置

半同步复制是异步复制和同步复制的折中方案,在性能和数据一致性之间取得平衡。

安装半同步复制扩展

bash
# 在主库和从库上执行
# 编辑 postgresql.conf
cat >> /var/lib/pgsql/15/data/postgresql.conf <<EOF
shared_preload_libraries = 'pg_semi_sync_master,pg_semi_sync_standby'
EOF

配置主库半同步复制

sql
-- 在主库上执行
ALTER SYSTEM SET semi_sync_master_enabled = on;
ALTER SYSTEM SET semi_sync_master_timeout = 5000;  -- 超时时间,单位毫秒
ALTER SYSTEM SET semi_sync_master_wait_for_feedback = on;
SELECT pg_reload_conf();

配置从库半同步复制

sql
-- 在从库上执行
ALTER SYSTEM SET semi_sync_standby_enabled = on;
SELECT pg_reload_conf();

验证半同步复制配置

sql
-- 在主库上执行
SELECT * FROM pg_stat_replication;

-- 检查半同步复制状态
SELECT * FROM pg_stat_get_semi_sync_master();

半同步复制最佳实践

  1. 合理设置超时时间:根据网络延迟调整 semi_sync_master_timeout
  2. 监控半同步状态:当半同步切换为异步时及时告警
  3. 结合复制槽使用:确保半同步从库断开连接后不会丢失 WAL 日志
  4. 考虑多从库场景:使用 synchronous_standby_names 配置多个半同步从库

3. 级联复制配置

级联复制允许从库从另一个从库复制数据,而不是直接从主库复制,适用于大规模部署场景。

配置中间从库

在中间从库(作为其他从库的主库)的 postgresql.conf 文件中添加以下配置:

ini
# 允许该从库作为其他从库的上游
max_wal_senders = 20
max_replication_slots = 20
wal_level = replica
hot_standby = on

配置级联从库

在级联从库上使用 pg_basebackup 从中间从库克隆数据:

bash
sudo -u postgres pg_basebackup \
  -h pg-slave1 \
  -U replicator \
  -D /var/lib/pgsql/15/data \
  -Fp -Xs -Pv -R \
  --slot=pg_cascade_slot

级联复制最佳实践

  1. 限制级联深度:建议级联深度不超过 2 层,避免延迟累积
  2. 每个层级使用复制槽:确保级联从库不会丢失 WAL 日志
  3. 监控级联延迟:特别关注末端从库的复制延迟
  4. 考虑网络拓扑:将级联从库部署在与中间从库相同的网络区域

4. 延迟复制配置

延迟复制允许从库故意延迟应用主库的 WAL 日志,用于时间点恢复,防止误操作影响所有节点。

配置延迟复制

在从库的 postgresql.conf 文件中添加以下配置:

ini
# 延迟 60 分钟应用 WAL 日志
recovery_min_apply_delay = '60min'

延迟复制使用场景

  1. 误操作恢复:当主库发生误操作(如误删除表)时,延迟从库可以保留误操作前的数据
  2. 测试环境:用于测试时间点恢复流程
  3. 数据分析:为数据分析提供特定时间点的快照

延迟复制最佳实践

  1. 合理设置延迟时间:根据业务需求设置,一般为 30 分钟到 24 小时
  2. 单独部署延迟从库:不要将延迟从库用于高可用目的
  3. 结合复制槽使用:确保延迟从库不会丢失 WAL 日志
  4. 定期测试恢复流程:验证延迟从库的时间点恢复功能

5. 加密复制连接配置

为了增强复制连接的安全性,建议配置 SSL/TLS 加密复制连接。

配置主库支持 SSL

  1. 生成 SSL 证书

    bash
    mkdir -p /var/lib/pgsql/15/ssl
    cd /var/lib/pgsql/15/ssl
    openssl req -new -x509 -days 365 -nodes -text -out server.crt -keyout server.key -subj "/CN=pg-master"
    chown postgres:postgres server.*
    chmod 600 server.key
  2. 配置主库 SSL

    ini
    # postgresql.conf
    ssl = on
    ssl_cert_file = 'ssl/server.crt'
    ssl_key_file = 'ssl/server.key'
    ssl_ca_file = ''  # 可选,用于验证客户端证书

配置从库使用 SSL 连接

编辑从库的 postgresql.auto.conf 文件:

ini
primary_conninfo = 'host=pg-master port=5432 user=replicator password=rep-pass sslmode=verify-ca sslrootcert=/var/lib/pgsql/15/ssl/ca.crt'

SSL 配置最佳实践

  1. 使用 verify-caverify-full:确保复制连接安全
  2. 定期轮换证书:避免证书过期导致复制中断
  3. 监控 SSL 连接状态:确保复制连接始终使用 SSL
  4. 考虑使用客户端证书:进一步增强安全性

流式复制监控与管理

1. 复制监控体系

内置视图监控

PostgreSQL 提供了丰富的内置视图用于监控复制状态:

sql
-- 主库复制状态监控
SELECT * FROM pg_stat_replication;

-- 复制槽状态监控
SELECT * FROM pg_replication_slots;

-- 从库 WAL 接收器状态监控
SELECT * FROM pg_stat_wal_receiver;

-- 从库恢复状态监控
SELECT * FROM pg_stat_wal_replay;

-- 从库备库状态监控
SELECT * FROM pg_stat_archiver;

Prometheus + Grafana 监控

安装和配置 pg_exporter

bash
# 下载最新版本的 pg_exporter
download_url=$(curl -s https://api.github.com/repos/prometheus-community/postgres_exporter/releases/latest | grep browser_download_url | grep linux-amd64 | cut -d '"' -f 4)
wget $download_url -O pg_exporter.tar.gz
tar xzf pg_exporter.tar.gz
cd pg_exporter-*
cp pg_exporter /usr/local/bin/

# 创建 pg_exporter 服务文件
cat > /etc/systemd/system/pg_exporter.service <<EOF
[Unit]
Description=PostgreSQL Exporter for Prometheus
After=network.target postgresql.service

[Service]
Type=simple
User=postgres
Environment=DATA_SOURCE_NAME=postgresql://postgres@localhost:5432/postgres?sslmode=disable
ExecStart=/usr/local/bin/pg_exporter --web.listen-address=:9187 --web.telemetry-path=/metrics
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

# 启动 pg_exporter 服务
systemctl daemon-reload
systemctl enable pg_exporter
systemctl start pg_exporter

Grafana 仪表盘推荐

  • 使用官方 PostgreSQL 仪表盘(ID: 9628)
  • 添加自定义复制监控面板:
    • 复制延迟趋势图
    • 复制状态变化告警
    • 复制槽使用率监控
    • WAL 日志生成与应用速率

日志监控

配置 PostgreSQL 日志记录复制相关信息:

ini
# postgresql.conf
log_replication_commands = on
log_replication_connections = on
log_min_messages = warning
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '

2. 复制槽管理最佳实践

日常监控

sql
-- 检查所有复制槽状态
SELECT 
    slot_name,
    slot_type,
    active,
    active_pid,
    pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS lag_size,
    age(now(), pg_stat_get_replication_slot_xact_bytes(slot_name)) AS inactive_time
FROM pg_replication_slots;

-- 查找占用大量磁盘空间的复制槽
SELECT 
    slot_name,
    pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS wal_retained
FROM pg_replication_slots
ORDER BY pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) DESC
LIMIT 5;

自动清理脚本

创建定期清理无效复制槽的脚本:

bash
#!/bin/bash

# 清理超过7天未活动的复制槽
sudo -u postgres psql -c "
DO $$
DECLARE
    rec RECORD;
BEGIN
    FOR rec IN
        SELECT slot_name
        FROM pg_replication_slots
        WHERE NOT active
        AND age(now(), pg_stat_get_replication_slot_xact_bytes(slot_name)) > interval '7 days'
    LOOP
        EXECUTE format('SELECT pg_drop_replication_slot(%L)', rec.slot_name);
        RAISE NOTICE 'Dropped inactive slot: %', rec.slot_name;
    END LOOP;
END $$;
"

3. 复制延迟处理

复制延迟原因分析

硬件资源问题

  • 从库 CPU 负载过高
  • 从库内存不足导致大量换页
  • 从库存储 IO 瓶颈
  • 主从网络延迟过大

配置问题

  • 从库 max_worker_processes 配置过低
  • 从库 hot_standby_feedback 未开启
  • 主库写入过于频繁

查询问题

  • 从库上长时间运行的只读查询阻塞 WAL 应用
  • 从库上的真空操作影响 WAL 应用

复制延迟解决方案

硬件优化

  • 为从库配置与主库相当或更好的硬件
  • 使用 NVMe SSD 存储
  • 确保主从之间网络延迟 < 1ms

配置优化

ini
# 从库 postgresql.conf 优化
max_worker_processes = 16
max_parallel_workers = 8
max_standby_streaming_delay = 30s
hot_standby_feedback = on
wal_receiver_status_interval = 5s

查询优化

  • 限制从库上查询的执行时间
  • 避免在从库上运行耗时分析查询
  • 定期在从库上执行 VACUUM ANALYZE 优化查询计划

监控与告警

  • 设置复制延迟告警阈值(如 > 30 秒)
  • 设置 WAL 日志堆积告警
  • 监控从库资源使用率

4. 从库重新同步

使用 pg_rewind 快速同步

当从库与主库数据差异较小时,使用 pg_rewind 工具快速同步,避免重新初始化:

bash
# 1. 确保主库开启了 wal_log_hints 或 data_checksums
# 2. 停止从库
systemctl stop postgresql-15

# 3. 检查从库与主库的差异
pg_rewind --source-server="host=pg-master user=replicator password=rep-pass" \
  --target-pgdata=/var/lib/pgsql/15/data \
  --dry-run

# 4. 执行实际同步
pg_rewind --source-server="host=pg-master user=replicator password=rep-pass" \
  --target-pgdata=/var/lib/pgsql/15/data \
  --write-recovery-conf

# 5. 启动从库
systemctl start postgresql-15

pg_rewind 适用场景

  • 从库因网络问题短暂断开连接
  • 从库因资源问题导致复制延迟过大
  • 主库故障转移后,旧主库需要重新作为从库加入集群

完全重新初始化

当从库数据差异较大或 pg_rewind 失败时,需要完全重新初始化:

bash
# 1. 停止从库
systemctl stop postgresql-15

# 2. 清空数据目录
rm -rf /var/lib/pgsql/15/data/*

# 3. 重新从主库克隆数据
sudo -u postgres pg_basebackup -h pg-master -U replicator -D /var/lib/pgsql/15/data -Fp -Xs -Pv -R

# 4. 启动从库
systemctl start postgresql-15

5. 复制故障诊断

常见复制故障及解决方案

故障现象可能原因解决方案
从库无法连接主库网络问题、主库未运行、pg_hba.conf 配置错误检查网络连接、主库状态、pg_hba.conf 配置
复制状态为 catchup从库正在追赶主库,通常发生在从库刚启动或断开连接后等待从库追上主库,监控复制延迟
WAL 日志丢失主库过早删除 WAL 日志,未使用复制槽或 wal_keep_size 配置过小使用复制槽,调整 wal_keep_size 参数
从库 WAL 应用阻塞从库上长时间运行的查询阻塞 WAL 应用终止长时间运行的查询,调整 max_standby_streaming_delay 参数
复制槽 inactive从库断开连接,复制槽未被使用检查从库状态,删除无效复制槽

6. 日常维护任务

定期执行的维护任务

  1. 每周:检查复制状态和延迟
  2. 每月:检查复制槽状态,清理无效复制槽
  3. 每季度:进行故障转移演练
  4. 每半年:重新评估复制配置和硬件资源
  5. 每年:更新 SSL 证书,进行全量从库重新同步测试

维护脚本示例

bash
#!/bin/bash

# 检查复制状态
REPLICATION_STATUS=$(sudo -u postgres psql -t -c "SELECT COUNT(*) FROM pg_stat_replication;")

if [ "$REPLICATION_STATUS" -eq 0 ]; then
    echo "WARNING: No replication slots are active!"
    # 发送告警
fi

# 检查复制延迟
MAX_DELAY=$(sudo -u postgres psql -t -c "SELECT MAX(now() - pg_last_xact_replay_timestamp()) FROM pg_stat_replication;")

if [[ "$MAX_DELAY" > "00:01:00" ]]; then
    echo "WARNING: Replication delay exceeds 1 minute!"
    # 发送告警
fi

生产环境最佳实践

1. 部署架构建议

硬件配置

  • 主从节点硬件配置尽量一致,避免性能瓶颈
  • 从库可适当增加内存,优化只读查询性能
  • 优先使用 NVMe SSD 存储,减少 I/O 延迟

网络设计

  • 使用专用网络进行复制流量传输
  • 确保主从之间网络延迟 < 1ms
  • 配置网络冗余,避免单点故障
  • 跨区域部署时,考虑使用专线或高质量 VPN

存储规划

  • 使用独立存储设备,避免与其他服务共享
  • 配置 RAID 10 或类似冗余存储
  • 考虑使用存储快照技术,加快从库创建速度

节点数量

  • 至少配置 2 个从库:1 个同步复制用于高可用,1 个异步复制用于读写分离
  • 大型集群可配置 3-5 个从库,分布在不同可用区

2. 配置最佳实践

核心配置参数

ini
# 主库配置
wal_level = replica
archive_mode = on
max_wal_senders = 20
max_replication_slots = 20
wal_keep_size = 16GB  # 至少保留 1 天的 WAL 日志
wal_compression = on  # PostgreSQL 14+ 支持

# 从库配置
hot_standby = on
hot_standby_feedback = on
max_standby_streaming_delay = 30s
wal_receiver_timeout = 60s
wal_receiver_status_interval = 10s

复制模式选择

业务场景推荐复制模式配置建议
金融/交易系统同步复制synchronous_commit = on
synchronous_standby_names = 'FIRST 1 (sync_replica)'
电商/社交平台半同步复制synchronous_commit = remote_write
semi_sync_master_timeout = 5000
日志/数据分析异步复制synchronous_commit = off

安全配置

  • 使用 scram-sha-256 认证方式
  • 严格限制复制用户的访问 IP 范围
  • 配置 SSL/TLS 加密复制连接
  • 定期轮换复制用户密码

3. 监控与告警策略

核心监控指标

指标类型具体指标告警阈值
复制状态复制延迟> 30 秒
复制状态复制连接状态断开 > 10 秒
复制槽不活跃复制槽> 7 天
复制槽WAL 保留大小> 50 GB
WAL 管理WAL 生成速率> 100 MB/秒
WAL 管理WAL 归档失败连续 3 次失败
从库资源CPU 使用率> 80% 持续 5 分钟
从库资源磁盘使用率> 90%

告警渠道

  • 短信/电话告警:用于严重故障(复制中断、延迟过大)
  • 邮件告警:用于普通告警(复制槽不活跃、资源使用率高)
  • 企业微信/钉钉告警:用于实时通知

监控系统集成

  • 集成 Prometheus + Grafana 构建可视化监控平台
  • 使用 Zabbix 或 Nagios 进行传统监控
  • 结合 ELK Stack 分析 PostgreSQL 日志

4. 维护与管理最佳实践

定期维护任务

维护任务频率具体操作
复制状态检查每周检查复制延迟、状态和复制槽
复制槽清理每月删除无效和不活跃的复制槽
从库重新同步测试每季度测试使用 pg_rewind 重新同步从库
故障转移演练每季度进行完整的故障转移测试
硬件资源评估每半年评估主从节点硬件资源,必要时升级
SSL 证书更新每年更新 SSL 证书,确保复制连接安全

故障处理流程

  1. 复制中断

    • 检查从库日志,确定中断原因
    • 检查主库复制槽状态
    • 尝试重启从库复制进程
    • 如无法恢复,使用 pg_rewind 或重新初始化从库
  2. 复制延迟过大

    • 分析延迟原因(硬件、网络、查询阻塞)
    • 优化从库资源配置
    • 调整 max_standby_streaming_delay 参数
    • 终止从库上长时间运行的查询
  3. 主库故障

    • 确认主库故障状态
    • 提升同步从库为主库
    • 重新配置其他从库连接到新主库
    • 验证新主库状态和复制拓扑

5. 性能优化建议

主库优化

  • 优化写入模式,减少大量小事务
  • 合理设置 checkpoint_completion_target 参数(建议 0.9)
  • 使用连接池,减少连接开销

从库优化

  • 配置适当的 shared_buffers 和 work_mem
  • 启用并行查询,提高只读性能
  • 定期执行 VACUUM ANALYZE,优化查询计划
  • 考虑使用 pg_prewarm 预加载热点数据

复制性能优化

  • 启用 WAL 压缩,减少网络传输量
  • 调整 wal_sender_timeout 和 wal_receiver_timeout
  • 考虑使用级联复制,分散主库压力
  • 跨区域部署时,使用异步复制减少主库延迟

6. 安全最佳实践

  • 最小权限原则:复制用户仅授予 REPLICATION 权限
  • 网络隔离:复制流量与业务流量分离
  • 加密传输:配置 SSL/TLS 加密复制连接
  • 定期审计:检查复制用户活动和连接日志
  • 备份保护:定期备份从库,确保数据安全
  • 访问控制:严格限制复制端口的访问范围

7. 升级与迁移策略

版本升级

  • 使用主从滚动升级,减少业务中断时间
  • 先升级从库,再进行主从切换
  • 升级后验证复制状态和数据一致性

迁移策略

  • 使用 pg_basebackup + 复制槽进行在线迁移
  • 跨版本迁移时,确保主库版本低于或等于从库版本
  • 迁移后进行性能测试和数据验证

PostgreSQL 10-16 版本差异

PostgreSQL 10 新特性

  • 引入物理复制槽
  • 增强逻辑复制支持
  • 改进 WAL 管理
  • 支持并行查询

PostgreSQL 11 新特性

  • 改进复制槽管理
  • 增强同步复制配置
  • 引入 pg_wal_replay_pause()/resume() 函数
  • 优化 WAL 发送机制

PostgreSQL 12 新特性

  • 移除 recovery.conf 文件,使用 postgresql.auto.conf 和 signal 文件
  • 引入 pg_promote() 函数
  • 增强复制监控视图
  • 优化复制性能

PostgreSQL 13 新特性

  • 引入 wal_keep_size 参数,替代 wal_keep_segments
  • 改进 pg_rewind 工具
  • 增强复制槽功能
  • 优化 WAL 压缩

PostgreSQL 14 新特性

  • 引入 write_lag/flush_lag/replay_lag 指标
  • 改进半同步复制性能
  • 增强复制监控功能
  • 优化 WAL 发送机制

PostgreSQL 15 新特性

  • 增强 pg_stat_replication 视图
  • 改进复制槽可靠性
  • 优化 WAL 管理
  • 增强 SSL/TLS 支持

PostgreSQL 16 新特性

  • 引入 WAL 压缩算法选择
  • 优化复制延迟计算
  • 增强级联复制支持
  • 改进复制槽自动清理机制
  • 增强复制监控指标

常见问题与解决方案

1. 从库无法连接主库

问题:从库无法连接到主库,报错 "could not connect to the primary server"

解决方案

  • 检查主库是否正在运行:systemctl status postgresql-15
  • 检查主库 listen_addresses 配置是否允许从库连接
  • 检查主库 pg_hba.conf 配置,确保允许从库 IP 和复制用户访问
  • 检查主从之间网络连接,使用 pingtelnet 测试
  • 验证复制用户密码是否正确

2. 复制延迟持续增加

问题:从库复制延迟持续增加,无法追上主库

解决方案

  • 检查从库资源使用率:top, iostat, vmstat
  • 检查从库上是否有长时间运行的查询:`SELECT * FROM pg_stat_activity WHERE state = 'active' ORDER BY query_start;
  • 调整从库 max_worker_processesmax_parallel_workers 参数
  • 考虑升级从库硬件,特别是存储设备
  • 检查主库写入负载,是否存在大量写入操作

3. 复制槽导致 WAL 堆积

问题:主库 WAL 日志堆积,磁盘空间不足,原因是存在不活跃的复制槽

解决方案

  • 查看复制槽状态:`SELECT * FROM pg_replication_slots WHERE NOT active;
  • 删除不活跃的复制槽:`SELECT pg_drop_replication_slot('inactive_slot');
  • 配置自动清理脚本,定期删除无效复制槽
  • 调整 wal_keep_size 参数,避免 WAL 过度堆积

4. 从库 WAL 应用阻塞

问题:从库 WAL 应用阻塞,复制延迟增加

解决方案

  • 检查从库上是否有长时间运行的查询阻塞 WAL 应用
  • 调整从库 max_standby_streaming_delay 参数
  • 考虑启用 hot_standby_feedback,防止主库清理从库正在使用的旧数据
  • 终止从库上长时间运行的查询

5. 主库故障后从库数据不一致

问题:主库故障后,多个从库数据不一致,无法确定哪个从库可以提升为主库

解决方案

  • 配置同步复制,确保至少有一个从库与主库数据一致
  • 使用复制槽,防止主库过早删除 WAL 日志
  • 定期进行故障转移演练,熟悉切换流程
  • 考虑使用自动化工具(如 Patroni)管理集群状态

6. 从库提升为主库后,其他从库无法连接

问题:从库提升为主库后,其他从库无法连接到新主库

解决方案

  • 检查新主库 listen_addresses 配置
  • 检查新主库 pg_hba.conf 配置,确保允许其他从库连接
  • 检查新主库 max_wal_senders 参数,确保有足够的 WAL 发送进程
  • 重新配置其他从库的 primary_conninfo,指向新主库
  • 重启其他从库的 PostgreSQL 服务

总结

流式复制是 PostgreSQL 高可用架构的基础,掌握其部署、配置和管理是 DBA 的核心技能。本文详细介绍了 PostgreSQL 流式复制的环境准备、主从配置、高级特性、监控管理和生产环境最佳实践,涵盖了从 PostgreSQL 10 到 16 的版本差异和新特性。

在实际部署中,需要根据业务需求选择合适的复制模式和架构,配置合理的参数,建立完善的监控和告警体系,并定期进行维护和演练。通过遵循最佳实践,可以构建稳定、可靠、高性能的 PostgreSQL 流式复制环境,确保业务数据的安全性和可用性。

对于 DBA 而言,持续学习 PostgreSQL 新版本的特性和优化,不断完善复制环境的配置和管理,是确保数据库服务高可用的关键。

常见问题与解决方案

1. 从库无法连接主库

问题:从库无法连接到主库,报错 "could not connect to the primary server"

解决方案

  • 检查主库是否正在运行
  • 检查主库的 listen_addresses 配置
  • 检查主库的 pg_hba.conf 配置,确保允许从库连接
  • 检查网络连接,确保从库可以访问主库的 5432 端口
  • 检查复制用户的密码是否正确

2. 复制延迟过高

问题:从库复制延迟持续增加

解决方案

  • 检查主库写入负载,是否有大量写入操作
  • 检查从库资源使用率,CPU、内存或磁盘 I/O 是否过高
  • 检查网络连接,是否存在网络瓶颈
  • 调整从库的 max_standby_streaming_delay 参数
  • 考虑使用更快的存储设备

3. 复制槽占用大量磁盘空间

问题:复制槽对应的 WAL 日志占用大量磁盘空间

解决方案

  • 检查对应的从库是否正在运行,复制是否正常
  • 如果从库已不再使用,删除对应的复制槽
  • 调整主库的 wal_keep_size 参数
  • 定期清理无效的复制槽

4. 主库 WAL 日志堆积

问题:主库 WAL 日志堆积,磁盘空间不足

解决方案

  • 检查 archive_command 是否正常工作
  • 检查复制槽状态,是否有长时间未活动的复制槽
  • 调整 wal_keep_size 参数,减少保留的 WAL 日志量
  • 检查从库是否正常接收 WAL 日志

5. 从库无法应用 WAL 日志

问题:从库报错 "could not apply WAL record"

解决方案

  • 检查主从库版本是否一致
  • 检查从库是否有未提交的事务
  • 检查主库是否有损坏的 WAL 日志
  • 考虑重新同步从库

总结

流式复制是 PostgreSQL 高可用架构的基础,通过合理配置和管理,可以构建稳定可靠的数据同步环境。在实际部署中,需要根据业务需求选择合适的复制模式,配置适当的参数,并建立完善的监控和管理机制。

通过遵循最佳实践,定期进行复制状态检查和故障转移测试,可以确保流式复制环境的可靠性和稳定性,为业务提供高可用性和数据安全性保障。对于 DBA 来说,掌握流式复制的部署、配置和管理是确保数据库服务连续性的重要技能。