PostgreSQL 15多主复制实现遇阻,求离线可用解决方案
PostgreSQL 离线环境多主复制可行方案
方案一:Slony-I 触发器式多主复制
Slony-I是老牌的PostgreSQL多主/双向复制工具,基于触发器实现,支持离线部署(仅安装阶段需联网下载包)。
- 安装步骤:
- 联网时,下载与你的PostgreSQL版本匹配的Slony-I离线安装包(rpm/deb或源码包),拷贝到所有离线服务器。
- 源码编译执行:
./configure --with-pgsql=/path/to/postgres/bin && make && make install;包管理安装直接用rpm -i或dpkg -i即可。
- 核心配置:
- 编写slonik脚本初始化集群:
执行脚本:cluster name = my_multimaster_cluster; node 1 admin conninfo = 'host=node1 port=5432 dbname=your_db user=postgres'; init cluster (id=1, comment='Primary Node 1');slonik < init_cluster.slonik - 添加第二个节点到集群:
执行脚本:cluster name = my_multimaster_cluster; node 1 admin conninfo = 'host=node1 port=5432 dbname=your_db user=postgres'; node 2 admin conninfo = 'host=node2 port=5432 dbname=your_db user=postgres'; add node (id=2, comment='Node 2');slonik < add_node2.slonik - 创建复制集指定同步表:
执行脚本:cluster name = my_multimaster_cluster; node 1 admin conninfo = 'host=node1 port=5432 dbname=your_db user=postgres'; create set (id=1, origin=1, comment='Replication Set'); set add table (set id=1, origin=1, id=1, fully qualified name='public.t1'); set add table (set id=1, origin=1, id=2, fully qualified name='public.t2');slonik < create_set.slonik - 在每个节点启动slon守护进程:
slon my_multimaster_cluster /path/to/your/slon.conf &
- 编写slonik脚本初始化集群:
- 注意:需提前规划冲突解决逻辑,比如通过触发器设置“最后写入获胜”,或自定义冲突处理规则。
方案二:pg_cron + dblink 自定义双向同步(轻量场景)
如果业务数据变更频率不高,这个轻量方案更省心,仅依赖PostgreSQL的两个扩展。
- 安装准备:
- 联网下载
pg_cron和dblink的离线安装包(对应PostgreSQL版本),拷贝到所有节点安装,或源码编译安装。 - 修改
postgresql.conf,添加shared_preload_libraries = 'pg_cron',重启PostgreSQL服务。
- 联网下载
- 配置步骤:
- 在所有节点创建dblink扩展:
CREATE EXTENSION IF NOT EXISTS dblink; - 创建同步函数(以node1同步node2数据为例):
CREATE OR REPLACE FUNCTION sync_node2_to_node1() RETURNS void AS $$ BEGIN -- 同步t1表,以id为唯一键,冲突时用新数据覆盖旧数据 INSERT INTO public.t1 (id, content, update_time) SELECT id, content, update_time FROM dblink('host=node2 port=5432 dbname=your_db user=postgres password=your_pwd', 'SELECT id, content, update_time FROM public.t1 WHERE update_time > (SELECT COALESCE(max(update_time), ''1970-01-01'') FROM public.t1)') AS sync_data(id int, content text, update_time timestamp) ON CONFLICT (id) DO UPDATE SET content = EXCLUDED.content, update_time = EXCLUDED.update_time; END; $$ LANGUAGE plpgsql; - 配置定时任务(每10秒同步一次):
SELECT cron.schedule('sync-node2-to-node1', '*/10 * * * * *', 'SELECT sync_node2_to_node1();'); - 在node2上反向配置同步函数和定时任务,实现双向同步。
- 在所有节点创建dblink扩展:
- 注意:适合数据量小、冲突场景少的业务,可根据需求调整同步频率和冲突规则。
方案三:pg_logical 双向主从(伪多主)
pg_logical本身是逻辑主从,但可配置双向订阅,实现类似多主的效果,适合需要逻辑复制特性的场景。
- 配置步骤:
- 在所有节点的
postgresql.conf中开启逻辑复制参数:
重启PostgreSQL服务。wal_level = logical max_replication_slots = 10 max_wal_senders = 10 wal_sender_timeout = 60s - 在node1创建发布(包含需要同步的表):
CREATE PUBLICATION pub_node1 FOR ALL TABLES IN SCHEMA public; - 在node2创建订阅(拉取node1的数据):
CREATE SUBSCRIPTION sub_node2_from_node1 CONNECTION 'host=node1 port=5432 dbname=your_db user=postgres' PUBLICATION pub_node1; - 反向配置:在node2创建
pub_node2发布,在node1创建sub_node1_from_node2订阅。
- 在所有节点的
- 注意:默认情况下,双向订阅遇到冲突会直接中断复制,需提前添加冲突处理逻辑,比如在表上创建触发器,或使用pg_logical的
conflict_handler参数自定义解决方式。
内容的提问来源于stack exchange,提问作者João Ferreira
相关产品推荐
相关产品推荐

