pglogical レプリケーションを使用してスイッチオーバーとフェイルオーバーを行う方法について説明します。
始める前に
pglogical レプリケーションが設定され、実用的な高可用性(HA)と障害復旧(DR)ソリューションが存在していて、論理レプリケーションが true を提供せず、すべてのデータベース オブジェクトの包括的なレプリケーションを提供しないことを確認したうえで、この構成をテストしてから使用してください。
pglogical 拡張機能の詳細については、pglogical についてをご覧ください。
pglogical を使用したデータ レプリケーションについては、AlloyDB for PostgreSQL と AlloyDB Omni の間でデータを複製すると AlloyDB Omni と他のデータベース間でデータを複製するをご覧ください。
pglogical レプリケーションによるスイッチオーバー
スイッチオーバーは、プロバイダ データベースとサブスクライバー データベースの間でロールを切り替えるために使用される制御されたプロセスです。スイッチオーバーを実行すると、2 つのデータベース(プロバイダとサブスクライバー)のロールが逆になります。プロバイダがサブスクライバーになり、サブスクライバーがプロバイダになります。
このスイッチオーバー機能は、オペレーティング システムのアップグレード、PostgreSQL のアップグレード、またはフェイルオーバー テストで重要です。
一方向レプリケーション構成でこれを実現するには、新しいプロバイダ / サブスクライバーの関係を設定し、古いプロバイダ / サブスクライバーのリレーションシップを削除する必要があります。
新しいプロバイダ / サブスクライバー構成を構築する
- データベースの変更を防ぐため、アプリケーションがプロバイダ システムへの書き込みを停止し、レプリケーション ラグをチェックして、すべてのトランザクションがサブスクライバー ノードで再生されていることを確認します。 - 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
- サブスクライバー データベースをプロバイダ データベースに変換します。 - 既存のサブスクライバーのサブスクリプションを停止します。
- 必要に応じてレプリケーション セットを追加します。
- 必要なテーブルをレプリケーション セットに追加します。
- 新しいサブスクライバー データベースに新しいサブスクライバー サブスクリプションを作成します。
- アプリケーションを新しいプロバイダにリダイレクトします。
 
- 既存のサブスクライバー データベースでサブスクリプションを停止します。このデータベースが新しいプロバイダになります。 - SELECT pglogical.alter_subscription_disable(SUBSCRIPTION_NAME);
- (省略可)元のプロバイダ データベースの定義と一致するレプリケーション セットを作成します。デフォルトのレプリケーション セットを使用している場合は、この操作は必要ありません。 - SELECT pglogical.create_replication_set(REPLICATION_SET_NAME);
- そのレプリケーション セットにテーブルを追加します。 - SELECT pglogical.replication_set_add_table(REPLICATION_SET_NAME, TABLE_NAME);- 次のように置き換えます。 - REPLICATION_SET_NAME: レプリケーション セットの名前。
- TABLE_NAME: スキーマ オーナーのテーブル名。例: ARRAY['public']
 
- 以前はプロバイダ データベースだった新しいサブスクライバー データベースで、 - 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>');
- プロバイダ ノードでサブスクリプションが機能しているかどうかを確認します。 - 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;
- レプリケーションが機能している場合は、新しいプロバイダ データベースを使用するようにアプリケーション接続文字列を変更し、アプリケーション ティアを再起動します。 
サブスクライバーの停止後に古いプロバイダ ノードでデータを変更すると、これらの変更は複製されず、データが失われます。元のプロバイダ データベースに複製されていないデータ変更がある場合、または元のプロバイダ(新しいサブスクライバー)が新しいプロバイダ データベース(古いサブスクライバー)と整合性のある状態になっていない場合は、新しい定サブスクライバー データベースを完全に構築する必要があります。
古いプロバイダとサブスクリプションを削除する
一方向レプリケーションが必要な場合は、古いプロバイダ / サブスクライバー構成を削除する必要があります。
- 新しいプロバイダで古いサブスクリプションを削除します。 - SELECT pglogical.drop_subscription('<subscription name>')
- 新しいサブスクライバーでレプリケーション セットを削除するか、レプリケーション セットからすべてのテーブルを削除します。 - 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: 最新の commit タイムスタンプを持つデータのバージョンが commit されるデータです。
- first_update_wins: 最も古いタイムスタンプを持つデータのバージョンが commit されるデータです。
双方向レプリケーションを設定するには、レプリケーションが双方向に行われるようにプロバイダとサブスクライバーを設定します。元のサブスクライバーは、元のプロバイダと同じレプリケーション セットを持つプロバイダにもなります。テーブルを作成して AlloyDB for PostgreSQL プロバイダ データベースのデフォルト レプリケーション セットに追加するを参照して、元のプロバイダ データベースの元のレプリケーション セットを複製するレプリケーション セットを作成します。
元のプロバイダで、新しいサブスクライバーを追加する必要があります。AlloyDB Omni サブスクライバー データベースにノードとサブスクリプションを作成するで、コマンド pglogical.create_subscription の synchronize_data パラメータが false に設定されていることを確認して、新しいサブスクライバーを作成します。これにより、データの初期テーブルコピーを回避できます。
pglogical レプリケーションによるフェイルオーバー
フェイルオーバーは、なんらかの理由でプロバイダ データベースが使用できなくなったときに発生します。この場合、サブスクライバー データベースを使用するようにアプリケーションを切り替える必要があります。
フェイルオーバーされたサブスクライバー データベースに誤って重複データが適用されないようにするには、サブスクリプションを無効にする必要があります。これにより、復元されたプロバイダの変更が、プロバイダが再び利用可能になったときに誤って適用されなくなります。
- サブスクライバー - test_sub_1を停止します。- SELECT pglogical.alter_subscription_disable(`test_sub_1`);
- ステータスが - 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})
- ステータスの出力で無効なキーワードを確認します。 
- 高可用性と障害復旧機能を維持するため、新しいプロバイダ / サブスクライバー構成を構築します。 
- 元々複製されていたすべてのテーブルを含む新しいレプリケーション セットを作成します。古いプロバイダ データベースが復元され、新しいサブスクライバーに変換された後に新しいサブスクライバーが作成されるようにするか、新しいサブスクライバーが作成されるようにします。 
- サブスクライバーを設定します。 
- 古いプロバイダ データベースを障害発生時まで復元できる場合は、このデータベースを新しいサブスクライバーとして設定します。同じ手順でサブスクリプションを作成し、 - pglogical.create_subscriptionコマンドの- synchronize_dataパラメータを- falseに設定して、初期のテーブルのコピーを回避します。
- WAL ファイルの蓄積を回避するため、復元されたノードで古いプロバイダ構成を削除します。 
- 古いプロバイダ データベースを使用している場合は、レプリケーション セット全体を削除するか、レプリケーション セットからすべてのテーブルを 1 つずつ削除します。 - SELECT pglogical.drop_replication_set('<replication set name>')- SELECT pglogical.replication_set_remove_table('<replication set name>','<table name>')
- 新しいノードに書き込むようにアプリケーションを切り替えます。