使用 pglogical 复制进行切换和故障切换

本页面介绍了如何使用 pglogical 复制进行切换和故障切换。

准备工作

在设置 pglogical 复制并提供可行的高可用性 (HA) 和灾难恢复 (DR) 解决方案,同时认识到逻辑复制未提供对所有数据库对象的 true 和全面复制后,您必须先测试此配置,然后才能开始使用它。

如需详细了解 pglogical 扩展程序,请参阅 pglogical 简介

如需了解如何使用 pglogical 进行数据复制,请参阅在 Google Cloud AlloyDB 和 AlloyDB Omni 之间复制数据以及在 AlloyDB Omni 和其他数据库之间复制数据

使用 pglogical 复制进行切换

切换是一个受控过程,用于在提供方数据库和订阅方数据库之间切换角色。执行切换时,两个数据库的角色(提供方和订阅方)会反转。提供方成为订阅方,订阅方成为提供方。

此切换功能对于操作系统升级、PostgreSQL 升级或故障切换测试非常重要。

如需在单向复制配置中实现此目的,您必须设置新的提供方/订阅方关系并移除旧的提供方/订阅方关系。

构建新的提供方/订阅方配置

  1. 停止应用向提供方系统写入数据,以防止进一步数据库更改,并检查复制延迟情况,以确保所有事务都在订阅方节点上重放:

    SELECT application_name,
        state,
        sync_state,
        client_addr,
        client_hostname,
        pg_wal_lsn_diff(pg_current_wal_lsn(),sent_lsn) AS sent_lag,
        pg_wal_lsn_diff(sent_lsn,flush_lsn) AS receiving_lag,
        pg_wal_lsn_diff(flush_lsn,replay_lsn) AS replay_lag,
        pg_wal_lsn_diff(pg_current_wal_lsn(),replay_lsn) AS total_lag,
        now()-reply_time AS reply_delay
    FROM pg_stat_replication
    ORDER BY client_hostname;
    

    当所有延迟字段均显示零时,表示复制是最新的,并且数据库已准备好进行切换。

    输出类似于以下内容:

    -[ RECORD 1 ]----+------------------------------
    application_name | test_sub_1
    state            | streaming
    sync_state       | async
    client_addr      | 10.45.0.80
    client_hostname  | 
    sent_lag         | 0
    receiving_lag    | 0
    replay_lag       | 0
    total_lag        | 0
    reply_delay      | 00:00:26.203433
    
  2. 将订阅方数据库转换为提供方数据库:

    1. 停止现有订阅方订阅。
    2. 添加复制集(如有必要)。
    3. 将必要的表添加到复制集中。
    4. 在新的订阅方数据库中构建新的订阅方订阅。
    5. 将应用重定向到新提供方。
  3. 停止现有订阅方数据库的订阅,该数据库会成为新提供方:

    SELECT pglogical.alter_subscription_disable(SUBSCRIPTION_NAME);
    
  4. (可选)创建与原始提供方数据库定义匹配的复制集。如果您使用的是默认复制集,则无需执行此操作:

    SELECT pglogical.create_replication_set(REPLICATION_SET_NAME);
    
  5. 将表添加到该复制集:

    SELECT pglogical.replication_set_add_table(REPLICATION_SET_NAME, TABLE_NAME);
    

    替换以下内容:

    • REPLICATION_SET_NAME:复制集的名称。
    • TABLE_NAME:架构所有者的表名称。例如,ARRAY['public']
  6. 在之前是提供方数据库的新订阅方数据库中,创建新的订阅,并将 synchronize_data 选项设置为 false,以防止初始表加载:

    SELECT pglogical.create_subscription (
               subscription_name := '<subscription name>',
               replication_sets := array['default'],
               synchronize_data := false,
               provider_dsn := 'host=<hostname or IP> port=5432 
               dbname=<db name> user=pglogical_replication password=<password>');
    
  7. 检查订阅是否在提供方节点上正常运行:

    SELECT application_name,
        state,
        sync_state,
        client_addr,
        client_hostname,
        pg_wal_lsn_diff(pg_current_wal_lsn(),sent_lsn) AS sent_lag,
        pg_wal_lsn_diff(sent_lsn,flush_lsn) AS receiving_lag,
        pg_wal_lsn_diff(flush_lsn,replay_lsn) AS replay_lag,
        pg_wal_lsn_diff(pg_current_wal_lsn(),replay_lsn) AS total_lag,
        now()-reply_time AS reply_delay
    FROM pg_stat_replication
    ORDER BY client_hostname;
    
  8. 如果复制正常运行,请更改应用连接字符串以使用新提供方数据库并重启应用层。

如果您在订阅方停止后更改旧提供方节点上的数据,则这些更改不会复制,从而导致数据丢失。如果原始提供方数据库中存在未复制的数据更改,或者原始提供方数据库(即新订阅方)的状态与新提供方数据库(即旧订阅方)的状态不一致,则您必须完全构建新订阅方数据库。

移除旧提供方和订阅

如果您需要单向复制,则必须移除旧提供方/订阅方配置。

  1. 移除新提供方上的旧订阅

    SELECT pglogical.drop_subscription('<subscription name>')
    
  2. 移除新订阅方上的复制集,或从复制集中移除所有表:

    SELECT pglogical.drop_replication_set('<replication set name>')
    
    SELECT pglogical.replication_set_remove_table('<replication set name>','<table name>')
    

双向复制

如需在不造成停机的情况下进行切换,或者确保不会因计划外的数据更改而导致数据丢失,您必须使用双向复制。在实现双向复制时,请考虑冲突解决方案,除非您已实施严格的控制措施来防止同时对两个节点进行写入访问。

您可以使用以下 pglogical.conflict_resolution 设置来设置冲突解决配置:

  • error:当检测到冲突时,订阅方会停止。
  • apply_remote:无论订阅方数据库中的数据如何,都始终应用传入的更改。这是默认设置。
  • keep_local:始终忽略有冲突的传入数据并舍弃有冲突的更改。
  • last_update_wins:具有最新提交时间戳的数据版本是已提交的数据
  • first_update_wins:具有最早时间戳的数据版本是已提交的数据

如需设置双向复制,请设置提供方和订阅方,以便复制在双向进行。原始订阅方还会成为提供方,并使用与原始提供方相同的复制集。如需创建复制集,以复制初始提供方数据库中的原始复制集,请参阅创建表并将其添加到 Google Cloud AlloyDB 提供方数据库中的默认复制集

您必须在原始提供方中添加新的订阅方。如需创建新的订阅方,确保命令 pglogical.create_subscriptionsynchronize_data 参数设置为 false,请参阅在 AlloyDB Omni 订阅方数据库中创建节点和订阅。这样可以避免初始表中的数据复制。

使用 pglogical 复制进行故障切换

如果提供方数据库因任何原因变得不可用,则会发生故障切换,您必须将应用切换为使用订阅方数据库。

为防止任何重复数据意外应用于已进行故障切换的订阅方数据库,您必须停用订阅。这可确保在已恢复的提供方再次可用时,系统不会错误地应用该提供方的更改。

  1. 停止订阅方 test_sub_1

    SELECT pglogical.alter_subscription_disable(`test_sub_1`);
    
  2. 检查状态是否设置为 disabled

    SELECT pglogical.show_subscription_status('test_sub_1');
    

    输出类似于以下内容:

    show_subscription_status                                                                           
    ----------------------------------------------------------------------------
    (test_sub1,disabled,subscriber,"host=10.45.0.108 port=5432 dbname=my_test_db user=pglogical_replication",subscriber,{failover_set},{all})
    
  3. 检查状态输出中停用的关键字。

  4. 构建新的提供方/订阅方配置,以保持高可用性和灾难恢复能力。

  5. 创建新的复制集,其中包含最初复制的所有表,以便在旧提供方数据库恢复并转换为新订阅方时构建新订阅方。

  6. 设置订阅方

  7. 如果您可以将旧提供方数据库恢复到发生故障的时间,请将此数据库设置为新订阅方。使用相同的步骤创建订阅,并将 pglogical.create_subscription 命令的 synchronize_data 参数设置为 false,以避免初始表副本。

  8. 移除已恢复节点上的旧提供方配置,以避免 WAL 文件堆积。

  9. 如果您使用的是旧提供方数据库,请删除完整的复制集,或从复制集中逐个移除所有表:

    SELECT pglogical.drop_replication_set('<replication set name>')
    
    SELECT pglogical.replication_set_remove_table('<replication set name>','<table name>')
    
  10. 切换应用以向新节点写入数据。

后续步骤