外观
PostgreSQL 流式复制环境部署与配置
流式复制是 PostgreSQL 高可用架构的核心基础,通过实时传输 WAL(Write-Ahead Logging)日志实现主从数据同步。对于生产环境而言,掌握流式复制的部署、配置和管理是构建高可用 PostgreSQL 集群的关键技能。
流式复制概述
什么是流式复制
流式复制是 PostgreSQL 9.0 引入的主从复制机制,通过 TCP/IP 连接将主库生成的 WAL 日志实时流传输到从库。从库接收到 WAL 日志后,立即写入本地 WAL 文件并异步应用,实现近实时的数据同步,通常延迟在毫秒级别。
流式复制的类型
- 异步复制:主库提交事务时不等待从库确认,性能最优但在主库故障时可能丢失数据
- 同步复制:主库必须等待至少一个从库确认 WAL 写入磁盘后才能提交事务,确保数据一致性但会降低主库写入性能
- 半同步复制:主库等待从库确认 WAL 接收(不一定写入磁盘),在性能和一致性之间取得平衡
流式复制的核心优势
- 高实时性:主从数据延迟通常在毫秒级别
- 数据可靠性:基于 WAL 日志确保数据一致性
- 部署灵活性:支持多种复制模式和拓扑结构
- 读写分离:从库支持只读查询,实现负载均衡
- 故障恢复:作为高可用架构的基础,支持快速故障转移
- 升级平滑:支持主从版本滚动升级
- 备份安全:从库备份不影响主库性能
环境准备
生产环境硬件要求
| 组件 | 一般业务配置 | 高并发业务配置 | 超大流量业务配置 |
|---|---|---|---|
| CPU | 4 核 | 8-16 核 | 16-32 核 |
| 内存 | 16 GB | 32-64 GB | 128 GB+ |
| 存储 | 200 GB NVMe SSD | 500 GB NVMe SSD | 1 TB+ NVMe SSD |
| 网络 | 万兆以太网 | 万兆以太网 | 25/100 千兆以太网 |
| IOPS | 10,000+ | 50,000+ | 100,000+ |
软件要求
| 软件 | 版本要求 | 生产建议 |
|---|---|---|
| PostgreSQL | 13 或以上 | 推荐 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-master | 192.168.1.10 | 主库 | 处理所有写入请求 |
| 从库 1 | pg-slave1 | 192.168.1.11 | 同步复制 | 高可用备用,确保数据一致性 |
| 从库 2 | pg-slave2 | 192.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-contrib2. 初始化主库
bash
# 在主库上执行
/usr/pgsql-15/bin/postgresql-15-setup initdb
systemctl start postgresql-15
systemctl enable postgresql-153. 配置主库参数
编辑 /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 存储建议设置为 2004. 配置主库认证
编辑 /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/archive7. 重启主库
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;状态解读:
state:streaming表示复制正常sync_state:sync表示同步复制,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');复制槽最佳实践:
- 每个从库一个复制槽:避免多个从库共享同一复制槽
- 定期清理无效复制槽:防止 WAL 日志堆积导致磁盘空间不足
- 监控复制槽延迟:设置告警阈值,当延迟超过阈值时及时处理
- 结合 wal_keep_size 使用:复制槽与 wal_keep_size 结合使用,提供双重保障
- 使用逻辑复制槽注意事项:逻辑复制槽会保留更多 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();半同步复制最佳实践:
- 合理设置超时时间:根据网络延迟调整
semi_sync_master_timeout - 监控半同步状态:当半同步切换为异步时及时告警
- 结合复制槽使用:确保半同步从库断开连接后不会丢失 WAL 日志
- 考虑多从库场景:使用
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级联复制最佳实践:
- 限制级联深度:建议级联深度不超过 2 层,避免延迟累积
- 每个层级使用复制槽:确保级联从库不会丢失 WAL 日志
- 监控级联延迟:特别关注末端从库的复制延迟
- 考虑网络拓扑:将级联从库部署在与中间从库相同的网络区域
4. 延迟复制配置
延迟复制允许从库故意延迟应用主库的 WAL 日志,用于时间点恢复,防止误操作影响所有节点。
配置延迟复制
在从库的 postgresql.conf 文件中添加以下配置:
ini
# 延迟 60 分钟应用 WAL 日志
recovery_min_apply_delay = '60min'延迟复制使用场景:
- 误操作恢复:当主库发生误操作(如误删除表)时,延迟从库可以保留误操作前的数据
- 测试环境:用于测试时间点恢复流程
- 数据分析:为数据分析提供特定时间点的快照
延迟复制最佳实践:
- 合理设置延迟时间:根据业务需求设置,一般为 30 分钟到 24 小时
- 单独部署延迟从库:不要将延迟从库用于高可用目的
- 结合复制槽使用:确保延迟从库不会丢失 WAL 日志
- 定期测试恢复流程:验证延迟从库的时间点恢复功能
5. 加密复制连接配置
为了增强复制连接的安全性,建议配置 SSL/TLS 加密复制连接。
配置主库支持 SSL
生成 SSL 证书:
bashmkdir -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配置主库 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 配置最佳实践:
- 使用
verify-ca或verify-full:确保复制连接安全 - 定期轮换证书:避免证书过期导致复制中断
- 监控 SSL 连接状态:确保复制连接始终使用 SSL
- 考虑使用客户端证书:进一步增强安全性
流式复制监控与管理
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_exporterGrafana 仪表盘推荐:
- 使用官方 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-15pg_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-155. 复制故障诊断
常见复制故障及解决方案:
| 故障现象 | 可能原因 | 解决方案 |
|---|---|---|
| 从库无法连接主库 | 网络问题、主库未运行、pg_hba.conf 配置错误 | 检查网络连接、主库状态、pg_hba.conf 配置 |
| 复制状态为 catchup | 从库正在追赶主库,通常发生在从库刚启动或断开连接后 | 等待从库追上主库,监控复制延迟 |
| WAL 日志丢失 | 主库过早删除 WAL 日志,未使用复制槽或 wal_keep_size 配置过小 | 使用复制槽,调整 wal_keep_size 参数 |
| 从库 WAL 应用阻塞 | 从库上长时间运行的查询阻塞 WAL 应用 | 终止长时间运行的查询,调整 max_standby_streaming_delay 参数 |
| 复制槽 inactive | 从库断开连接,复制槽未被使用 | 检查从库状态,删除无效复制槽 |
6. 日常维护任务
定期执行的维护任务:
- 每周:检查复制状态和延迟
- 每月:检查复制槽状态,清理无效复制槽
- 每季度:进行故障转移演练
- 每半年:重新评估复制配置和硬件资源
- 每年:更新 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 证书,确保复制连接安全 |
故障处理流程:
复制中断:
- 检查从库日志,确定中断原因
- 检查主库复制槽状态
- 尝试重启从库复制进程
- 如无法恢复,使用 pg_rewind 或重新初始化从库
复制延迟过大:
- 分析延迟原因(硬件、网络、查询阻塞)
- 优化从库资源配置
- 调整 max_standby_streaming_delay 参数
- 终止从库上长时间运行的查询
主库故障:
- 确认主库故障状态
- 提升同步从库为主库
- 重新配置其他从库连接到新主库
- 验证新主库状态和复制拓扑
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 和复制用户访问 - 检查主从之间网络连接,使用
ping和telnet测试 - 验证复制用户密码是否正确
2. 复制延迟持续增加
问题:从库复制延迟持续增加,无法追上主库
解决方案:
- 检查从库资源使用率:
top,iostat,vmstat - 检查从库上是否有长时间运行的查询:`SELECT * FROM pg_stat_activity WHERE state = 'active' ORDER BY query_start;
- 调整从库
max_worker_processes和max_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 来说,掌握流式复制的部署、配置和管理是确保数据库服务连续性的重要技能。
