You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL 15多主复制实现遇阻,求离线可用解决方案

PostgreSQL 离线环境多主复制可行方案

方案一:Slony-I 触发器式多主复制

Slony-I是老牌的PostgreSQL多主/双向复制工具,基于触发器实现,支持离线部署(仅安装阶段需联网下载包)。

  • 安装步骤:
    1. 联网时,下载与你的PostgreSQL版本匹配的Slony-I离线安装包(rpm/deb或源码包),拷贝到所有离线服务器。
    2. 源码编译执行:./configure --with-pgsql=/path/to/postgres/bin && make && make install;包管理安装直接用rpm -i或dpkg -i即可。
  • 核心配置:
    1. 编写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
    2. 添加第二个节点到集群:
      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
    3. 创建复制集指定同步表:
      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
    4. 在每个节点启动slon守护进程:
      slon my_multimaster_cluster /path/to/your/slon.conf &
      
  • 注意:需提前规划冲突解决逻辑,比如通过触发器设置“最后写入获胜”,或自定义冲突处理规则。

如果业务数据变更频率不高,这个轻量方案更省心,仅依赖PostgreSQL的两个扩展。

  • 安装准备:
    1. 联网下载pg_cron和dblink的离线安装包(对应PostgreSQL版本),拷贝到所有节点安装,或源码编译安装。
    2. 修改postgresql.conf,添加shared_preload_libraries = 'pg_cron',重启PostgreSQL服务。
  • 配置步骤:
    1. 在所有节点创建dblink扩展:
      CREATE EXTENSION IF NOT EXISTS dblink;
      
    2. 创建同步函数(以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;
      
    3. 配置定时任务(每10秒同步一次):
      SELECT cron.schedule('sync-node2-to-node1', '*/10 * * * * *', 'SELECT sync_node2_to_node1();');
      
    4. 在node2上反向配置同步函数和定时任务,实现双向同步。
  • 注意:适合数据量小、冲突场景少的业务,可根据需求调整同步频率和冲突规则。

方案三:pg_logical 双向主从(伪多主)

pg_logical本身是逻辑主从,但可配置双向订阅,实现类似多主的效果,适合需要逻辑复制特性的场景。

  • 配置步骤:
    1. 在所有节点的postgresql.conf中开启逻辑复制参数:
      wal_level = logical
      max_replication_slots = 10
      max_wal_senders = 10
      wal_sender_timeout = 60s
      
      重启PostgreSQL服务。
    2. 在node1创建发布(包含需要同步的表):
      CREATE PUBLICATION pub_node1 FOR ALL TABLES IN SCHEMA public;
      
    3. 在node2创建订阅(拉取node1的数据):
      CREATE SUBSCRIPTION sub_node2_from_node1 
      CONNECTION 'host=node1 port=5432 dbname=your_db user=postgres' 
      PUBLICATION pub_node1;
      
    4. 反向配置:在node2创建pub_node2发布,在node1创建sub_node1_from_node2订阅。
  • 注意:默认情况下,双向订阅遇到冲突会直接中断复制,需提前添加冲突处理逻辑,比如在表上创建触发器,或使用pg_logical的conflict_handler参数自定义解决方式。

内容的提问来源于stack exchange,提问作者João Ferreira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 18:55:31