在大规模业务场景中,数据可靠性与可用性至关重要。本文结合真实生产环境案例,分享基于PostgreSQL逻辑复制(Logical Replication)与流复制(Streaming Replication)建设高可用架构的全流程,包括选型、部署、故障切换与优化思考,为有一定数据库运维和后端基础的读者提供可落地的实战经验。
业务特点:
可用性需求:
技术现状:
流复制 vs 逻辑复制
组件选择
方案对比表
| 特性 | 流复制 | 逻辑复制 | Patroni+Etcd | | ------------------- | --------------- | --------------- | ------------------ | | 复制粒度 | 实例 | 表 | N/A | | 延迟 | ~10ms | ~100ms | N/A | | 断点续传 | 原生支持 | 需手工重建订阅 | N/A | | HA 管理 | 需外部脚本 | 需外部脚本 | 原生支持 Leader 选举 | | 弹性扩展 | 较弱 | 强 | N/A |
综合评估:结合生产环境需求,主备流复制保证主节点容灾,逻辑复制用于跨集群或业务拆分订阅,Patroni+Etcd 做整个集群的自动选主与故障恢复。
postgresql.conf:
# 开启逻辑复制
wal_level = logical # logical 或更高
max_replication_slots = 10 # 根据业务订阅需求配置
max_wal_senders = 10 # 与 max_replication_slots 保持一致
wal_keep_segments = 512 # 保留 WAL 文件数量
synchronous_commit = on # 保证事务提交后实时推送副本
pg_hba.conf:
# 允许复制角色连接
host replication repl_user standby_ip/32 md5
host all all standby_ip/32 md5
重启 PostgreSQL:
systemctl restart postgresql-12
pip3 install patroni[etcd]
# 安装 etcd
wget https://github.com/etcd-io/etcd/releases/download/v3.4.15/etcd-v3.4.15-linux-amd64.tar.gz
scope: pg_cluster
namespace: /db/
name: postgresql-1
restapi:
listen: 0.0.0.0:8008
connect_address: 10.0.1.11:8008
etcd:
host: 127.0.0.1:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
initdb:
- encoding: UTF8
- data-checksums
postgresql:
listen: 0.0.0.0:5432
connect_address: 10.0.1.11:5432
data_dir: /data/pg12/data
bin_dir: /usr/pgsql-12/bin
parameters:
wal_level: logical
max_wal_senders: 10
max_replication_slots: 10
wal_keep_segments: 512
synchronous_commit: on
authentication:
replication:
username: repl_user
password: repl_password
superuser:
username: postgres
password: super_password
启动 Patroni:
patroni /etc/patroni.yml &
等待 etcd 中选举出 Leader,其他节点自动跟随。
-- 创建复制角色
CREATE ROLE repl_logical WITH REPLICATION PASSWORD 'repl_logic_pw' LOGIN;
-- 定义发布
CREATE PUBLICATION pub_all FOR TABLE orders, order_items, customers;
CREATE SUBSCRIPTION sub_pub_all
CONNECTION 'host=10.0.1.11 port=5432 user=repl_logical password=repl_logic_pw dbname=mydb'
PUBLICATION pub_all;
-- 查看发布状态
SELECT * FROM pg_publication;
-- 查看订阅状态
SELECT * FROM pg_subscription;
-- 查看复制槽使用情况
SELECT * FROM pg_replication_slots;
# prometheus.yml snippet
- job_name: 'postgres'
static_configs:
- targets: ['10.0.1.11:9187','10.0.1.12:9187']
Grafana 可视化看板:
复制槽累积引发磁盘占满: 问题:复制槽在订阅端宕机后无法自动清理,WAL 文件持续增长; 解决:定期清理无效订阅并根据业务设置合理的 wal_keep_segments。
逻辑复制延迟过高: 问题:大事务导入导致订阅端堆积; 解决:控制批量提交大小(commit delay
),或拆分为小事务; 示例:
BEGIN;
INSERT INTO orders VALUES (...);
INSERT INTO order_items VALUES (...);
COMMIT;
-- 控制单批事务大小在 10k 行以内
Patroni 节点漂移(split-brain): 问题:etcd 网络抖动导致多主; 解决:调整 DCS 参数 (ttl
, retry_timeout
) 并加固 etcd 集群网络可靠性。
主库 DDL 操作与逻辑复制冲突: 问题:逻辑复制默认不复制所有 DDL; 解决:采用 pglogical
插件补充 DDL 同步,或在维护窗口内手动执行 DDL。
通过以上实战经验分享,读者可以在真实生产环境中快速搭建高可用、低延迟且灵活可扩展的 PostgreSQL 复制架构,为大规模业务保驾护航。