11 KiB
11 KiB
pglogical 双向逻辑复制部署指南
本文档介绍如何在两台 PostgreSQL 16 数据库之间部署 pglogical 扩展,实现支持 TLS 的异步双向逻辑复制,并包含冲突处理、监控及与 Bucardo 的对比。
目录
- pglogical 简介
- 环境准备
- 安装 pglogical 扩展
- 配置 PostgreSQL 参数
- 创建复制用户
- 创建节点与复制集
- 建立双向订阅
- 验证复制状态
- 冲突解决策略
- TLS 配置示例
- 常用维护命令
- 监控指标
- 性能与延迟优化建议
- 优缺点总结
- 推荐部署参数模板
- 与 Bucardo 的对比
- 附录:SQL 脚本模板
pglogical 简介
| 特性 | 说明 |
|---|---|
| 类型 | 基于 WAL 的逻辑复制扩展(由 2ndQuadrant 开发,后并入 EDB/PGDG) |
| 复制粒度 | 表级 / 库级,支持选择性复制 |
| 拓扑 | 单向、一主多从、多主(双向)均可 |
| 延迟 | 秒级(异步逻辑流式复制) |
| 冲突 | 可配置(默认“先到先得”,支持自定义冲突解决) |
| DDL 支持 | 不自动复制 DDL(需两端结构一致) |
| 安全 | 继承 PostgreSQL 的 TLS / SCRAM / 证书机制 |
| 推荐版本 | PostgreSQL 13~17(pglogical 2.x/3.x) |
与 Bucardo 相比,pglogical 更现代、稳定、性能更高,且原生支持异步双向复制(multi-master)和 TLS 加密。
环境准备
假设部署架构如下:
| 节点 | 主机名 | 数据库 | 角色 |
|---|---|---|---|
| A | pgA.svc.plus |
account |
node_a |
| B | pgB.svc.plus |
account |
node_b |
两台节点均运行 PostgreSQL 16,并且网络互通。
安装 pglogical 扩展
在两台节点上安装 pglogical 软件包:
-
Ubuntu / Debian
sudo apt install postgresql-16-pglogical -
Red Hat / CentOS
sudo yum install pglogical_16
安装完成后,在 account 数据库中创建扩展验证:
psql -d account -c "CREATE EXTENSION IF NOT EXISTS pglogical;"
配置 PostgreSQL 参数
在两台节点的 postgresql.conf 中设置逻辑复制所需参数:
# 逻辑复制基础
wal_level = logical
max_wal_senders = 10
max_replication_slots = 10
max_worker_processes = 10
max_logical_replication_workers = 8
# 建议优化
shared_preload_libraries = 'pglogical'
track_commit_timestamp = on
在 pg_hba.conf 中授权(建议开启 TLS):
hostssl replication repl_user <peer_ip>/32 scram-sha-256
hostssl all pglogical <peer_ip>/32 scram-sha-256
注意:更新配置后需要重启服务生效:
sudo systemctl restart postgresql@16-main
创建复制用户
在两台数据库上分别执行:
CREATE ROLE pglogical LOGIN REPLICATION PASSWORD 'StrongPass';
GRANT ALL PRIVILEGES ON DATABASE account TO pglogical;
创建节点与复制集
节点 A
-- 启用扩展
CREATE EXTENSION IF NOT EXISTS pglogical;
-- 注册节点
SELECT pglogical.create_node(
node_name := 'node_a',
dsn := 'host=pgA.svc.plus port=5432 dbname=account user=pglogical password=StrongPass sslmode=verify-full'
);
-- 创建复制集,包含 public 模式下所有表
SELECT pglogical.create_replication_set('rep_all');
SELECT pglogical.replication_set_add_all_tables('rep_all', ARRAY['public']);
节点 B
CREATE EXTENSION IF NOT EXISTS pglogical;
SELECT pglogical.create_node(
node_name := 'node_b',
dsn := 'host=pgB.svc.plus port=5432 dbname=account user=pglogical password=StrongPass sslmode=verify-full'
);
SELECT pglogical.create_replication_set('rep_all');
SELECT pglogical.replication_set_add_all_tables('rep_all', ARRAY['public']);
建立双向订阅
节点 A 订阅节点 B
SELECT pglogical.create_subscription(
subscription_name := 'sub_from_b',
provider_dsn := 'host=pgB.svc.plus port=5432 dbname=account user=pglogical password=StrongPass sslmode=verify-full',
replication_sets := ARRAY['rep_all'],
synchronize_structure := false,
synchronize_data := true,
forward_origins := '{}'
);
节点 B 订阅节点 A
SELECT pglogical.create_subscription(
subscription_name := 'sub_from_a',
provider_dsn := 'host=pgA.svc.plus port=5432 dbname=account user=pglogical password=StrongPass sslmode=verify-full',
replication_sets := ARRAY['rep_all'],
synchronize_structure := false,
synchronize_data := true,
forward_origins := '{}'
);
参数说明:
synchronize_structure = false:假设双方的表结构已对齐。synchronize_data = true:初次创建时自动进行数据同步。forward_origins = '{}':防止回环复制,避免来自对端的写入再次回传。sslmode = verify-full:开启 TLS 并校验证书。
验证复制状态
常用验证命令:
SELECT * FROM pglogical.show_subscription_status();
SELECT * FROM pglogical.show_node_info();
查看流复制进度:
SELECT application_name, state, sent_lsn, write_lsn, flush_lsn, replay_lsn
FROM pg_stat_replication;
日志中出现如下信息表明表同步完成:
pglogical: initial copy of table "public.users" finished
冲突解决策略
pglogical 默认策略为 “first commit wins”。在开启 track_commit_timestamp = on 后,可以使用以下策略:
| 策略 | 含义 |
|---|---|
error |
发生冲突时报错并终止复制 |
apply_remote |
使用远端数据覆盖本地 |
keep_local |
保留本地数据,忽略远端变更 |
latest_commit |
保留提交时间更晚的行 |
custom |
调用自定义函数处理冲突 |
示例:
SELECT pglogical.alter_subscription_options(
subscription_name := 'sub_from_b',
options := '{conflict_resolution=latest_commit}'
);
TLS 配置示例
使用 libpq 连接参数即可启用 TLS:
SELECT pglogical.create_subscription(
subscription_name := 'sub_from_b',
provider_dsn := 'host=pgB.svc.plus port=5432 dbname=account user=pglogical password=StrongPass sslmode=verify-full sslrootcert=/etc/ssl/rootCA.crt sslcert=/etc/ssl/client.crt sslkey=/etc/ssl/client.key',
replication_sets := ARRAY['rep_all']
);
sslmode 支持 require、verify-ca、verify-full,推荐使用 verify-full 并确保证书 CN/SAN 与主机名匹配。
常用维护命令
| 操作 | SQL 命令 |
|---|---|
| 暂停订阅 | SELECT pglogical.alter_subscription_disable('sub_from_b'); |
| 恢复订阅 | SELECT pglogical.alter_subscription_enable('sub_from_b', true); |
| 删除订阅 | SELECT pglogical.drop_subscription('sub_from_b'); |
| 删除节点 | SELECT pglogical.drop_node('node_a'); |
监控指标
| 表 / 视图 | 说明 |
|---|---|
pglogical.show_subscription_status() |
订阅状态(延迟、复制槽、错误) |
pg_stat_replication |
WAL 流复制进度 |
pglogical.replication_set |
当前同步的表集合 |
pglogical.local_sync_status |
同步阶段(initial / catching-up / ready) |
性能与延迟优化建议
| 参数 | 推荐值 | 说明 |
|---|---|---|
max_replication_slots |
≥ 10 | 允许更多并发订阅 |
max_wal_senders |
≥ 10 | 支持更多并发流复制连接 |
maintenance_work_mem |
≥ 128MB | 提高初始数据复制效率 |
synchronous_commit |
off |
降低写入延迟(异步复制场景) |
wal_compression |
on |
降低网络传输量 |
subscription_apply_delay |
0–60 秒 | 可配置延迟重放,满足业务需求 |
优缺点总结
| 优点 | 缺点 |
|---|---|
| 原生逻辑复制,性能远优于 Bucardo | 不复制 DDL,需保证结构一致 |
| 支持 TLS / SCRAM / 双向复制 | 需要安装扩展(非纯 SQL) |
冲突处理策略灵活(latest_commit / custom) |
不适合同一行的高并发双写场景 |
| 延迟低(秒级) | 不支持系统表复制 |
推荐部署参数模板
| 项 | 配置 |
|---|---|
| 节点 A/B | PostgreSQL 16 + pglogical 3.6 |
| 通道 | TLS (sslmode=verify-full) |
| 复制方向 | 双向 |
| 延迟 | 2–10 秒 |
| 冲突策略 | latest_commit |
| 初始同步 | synchronize_data = true |
| 同步集 | 业务表(users、identities、sessions) |
| DDL 管理 | GitOps + 同步迁移脚本 |
| 监控 | Grafana + pg_stat_replication + pglogical 状态视图 |
与 Bucardo 的对比
| 维度 | pglogical | Bucardo |
|---|---|---|
| 复制机制 | WAL 逻辑流 | 触发器 + 队列 |
| 延迟 | 秒级 | 秒级至分钟级 |
| 性能 | 高 | 中 |
| 冲突控制 | 内置多策略 | Perl 自定义 |
| 安全 | 原生支持 TLS | 依赖 libpq TLS |
| 部署复杂度 | 中(需扩展) | 低(Perl 脚本) |
| 推荐场景 | 跨 Region 双向 / 实时异步复制 | 异地多活、低写负载场景 |
附录:SQL 脚本模板
可将上述配置整理为以下 SQL 脚本:
setup-node-a.sql
-- 节点 A 初始化
CREATE EXTENSION IF NOT EXISTS pglogical;
SELECT pglogical.create_node(
node_name := 'node_a',
dsn := 'host=pgA.svc.plus port=5432 dbname=account user=pglogical password=StrongPass sslmode=verify-full'
);
SELECT pglogical.create_replication_set('rep_all');
SELECT pglogical.replication_set_add_all_tables('rep_all', ARRAY['public']);
SELECT pglogical.create_subscription(
subscription_name := 'sub_from_b',
provider_dsn := 'host=pgB.svc.plus port=5432 dbname=account user=pglogical password=StrongPass sslmode=verify-full',
replication_sets := ARRAY['rep_all'],
synchronize_structure := false,
synchronize_data := true,
forward_origins := '{}'
);
setup-node-b.sql
-- 节点 B 初始化
CREATE EXTENSION IF NOT EXISTS pglogical;
SELECT pglogical.create_node(
node_name := 'node_b',
dsn := 'host=pgB.svc.plus port=5432 dbname=account user=pglogical password=StrongPass sslmode=verify-full'
);
SELECT pglogical.create_replication_set('rep_all');
SELECT pglogical.replication_set_add_all_tables('rep_all', ARRAY['public']);
SELECT pglogical.create_subscription(
subscription_name := 'sub_from_a',
provider_dsn := 'host=pgA.svc.plus port=5432 dbname=account user=pglogical password=StrongPass sslmode=verify-full',
replication_sets := ARRAY['rep_all'],
synchronize_structure := false,
synchronize_data := true,
forward_origins := '{}'
);
verify-replication.sql
-- 验证订阅状态
SELECT * FROM pglogical.show_subscription_status();
SELECT * FROM pglogical.show_node_info();
-- 检查复制进度
SELECT application_name, state, sent_lsn, write_lsn, flush_lsn, replay_lsn
FROM pg_stat_replication;
以上脚本可根据实际业务需要调整数据库名称、节点信息及复制集内容。