pgactive を使用したアクティブ/アクティブレプリケーションのサポート
pgactive
拡張は、アクティブ/アクティブレプリケーションを使用して、複数の RDS for PostgreSQL データベースに対する書き込み操作をサポートおよび調整します。Amazon RDS for PostgreSQL は、次のバージョンの pgactive
拡張機能をサポートしています。
-
RDS for PostgreSQL 16.1 またはそれ以降の 16 バージョン
-
RDS for PostgreSQL 15.4-R2 以降のバージョン 15
-
RDS for PostgreSQL 14.10 以降のバージョン 14
-
RDS for PostgreSQL 13.13 以降のバージョン 13
-
RDS for PostgreSQL 12.17 以降のバージョン 12
-
RDS for PostgreSQL 11.22
注記
レプリケーション設定に複数のデータベースに対する書き込み操作があると、競合が発生する可能性があります。詳細については、「アクティブ/アクティブレプリケーションの競合の処理」を参照してください。
トピック
pgactive 拡張機能の初期化
RDS for PostgreSQL DB インスタンスの pgactive
拡張機能を初期化するには、rds.enable_pgactive
パラメータの値を 1
に設定し、データベースに拡張を作成します。これを行うと、rds.logical_replication
パラメータと track_commit_timestamp
パラメータが自動的に有効になり、wal_level
の値が logical
に設定されます。
これらのタスクを実行するには、rds_superuser
ロールとしてアクセス許可が必要です。
AWS Management Console または AWS CLI を使用して、必要な RDS for PostgreSQL DB インスタンスを作成できます。以下のステップでは、RDS for PostgreSQL DB インスタンスがカスタム DB パラメータグループに関連付けられていることを前提としています。カスタム DB パラメータグループの作成については、「Amazon RDS のパラメータグループ」を参照してください。
pgactive 拡張機能を初期化するには
AWS Management Console にサインインし、Amazon RDS コンソール https://console.aws.amazon.com/rds/
を開きます。 -
ナビゲーションペインで、RDS for PostgreSQL DB インスタンスを選択します。
-
RDS for PostgreSQL DB インスタンスの [設定] タブを開きます。インスタンスの詳細で、[DB インスタンスパラメータグループ] リンクを見つけます。
-
リンクを選択して、RDS for PostgreSQL DB インスタンスに関連付けられたカスタムパラメータを開きます。
rds.enable_pgactive
パラメータを見つけて1
に設定し、pgactive
機能を初期化します。[Save changes] (変更の保存) をクリックします。
Amazon RDS コンソールのナビゲーションペインで、[データベース] を選択します。
RDS for PostgreSQL DB インスタンスを選択し、[アクション] メニューから [再起動] を選択します。
DB インスタンスの再起動を確定して、変更を有効にします。
DB インスタンスが使用可能になったら、
psql
または他の任意の PostgreSQL インスタンスを使用して RDS for PostgreSQL DB インスタンスに接続します。次の例では、RDS for PostgreSQL DB インスタンスに
postgres
という名前のデフォルトデータベースがあることを前提としています。psql --host=
mydb.111122223333
.aws-region
.rds.amazonaws.com --port=5432 --username=master username
--password --dbname=postgres
pgactive が初期化されていることを確認するには、次のコマンドを実行します。
postgres=>
SELECT setting ~ 'pgactive' FROM pg_catalog.pg_settings WHERE name = 'shared_preload_libraries';
pgactive
がshared_preload_libraries
にある場合、前述のコマンドは以下を返します。?column? ---------- t
次のように拡張を作成します。
postgres=>
CREATE EXTENSION pgactive;
pgactive 拡張機能を初期化するには
AWS CLI を使用して pgactive
を設定するには、次の手順に示すように、modify-db-parameter-group オペレーションを呼び出してカスタムパラメータグループ内の特定のパラメータを変更します。
AWS CLI コマンドを使用して
rds.enable_pgactive
を1
に設定し、RDS for PostgreSQL DB インスタンスのpgactive
機能を初期化します。postgres=>
aws rds modify-db-parameter-group \ --db-parameter-group-namecustom-param-group-name
\ --parameters "ParameterName=rds.enable_pgactive,ParameterValue=1,ApplyMethod=pending-reboot" \ --regionaws-region
-
次の AWS CLI コマンドを使用して RDS for PostgreSQL DB インスタンスを再起動し、
pgactive
ライブラリを初期化します。aws rds reboot-db-instance \ --db-instance-identifier
your-instance
\ --regionaws-region
インスタンスが使用可能になったら、
psql
を使用して RDS for PostgreSQL DB インスタンスに接続します。psql --host=
mydb.111122223333
.aws-region
.rds.amazonaws.com --port=5432 --username=master user
--password --dbname=postgres
次のように拡張を作成します。
postgres=>
CREATE EXTENSION pgactive;
RDS for PostgreSQL DB インスタンスのアクティブ/アクティブレプリケーションの設定
次の手順は、同じリージョンで PostgreSQL 15.4 以降を実行している 2 つの RDS for PostgreSQL DB インスタンス間でアクティブ/アクティブレプリケーションを開始する方法を示しています。マルチリージョンの高可用性の例を実行するには、2 つの異なるリージョンに Amazon RDS for PostgreSQL インスタンスをデプロイし、VPC ピアリングを設定する必要があります。詳細については、「VPC ピアリング接続」を参照してください。
注記
複数のリージョン間でトラフィックを送信すると、追加コストが発生する可能性があります。
次の手順では、RDS for PostgreSQL DB インスタンスが pgactive
拡張を使用して設定されていることを前提としています。詳細については、「pgactive 拡張機能の初期化」を参照してください。
pgactive
拡張を使用して最初の RDS for PostgreSQL DB インスタンスを設定するには
次の例は、pgactive
グループの作成方法と、RDS for PostgreSQL DB インスタンスで pgactive
拡張を作成するために必要なその他の手順を示しています。
psql
または別のクライアントツールを使用して、最初の RDS for PostgreSQL DB インスタンスに接続します。psql --host=
firstinstance.111122223333
.aws-region
.rds.amazonaws.com --port=5432 --username=master username
--password --dbname=postgres
次のコマンドを使用して RDS for PostgreSQL インスタンスにデータベースを作成します。
postgres=>
CREATE DATABASEapp
;次のコマンドを使用して、接続先を新しいデータベースに切り替えます。
\c
app
shared_preload_libraries
パラメータにpgactive
が含まれているかどうかを確認するには、次のコマンドを実行します。app=>
SELECT setting ~ 'pgactive' FROM pg_catalog.pg_settings WHERE name = 'shared_preload_libraries';?column? ---------- t
-
次の SQL ステートメントを使用して、サンプルのテーブルを作成および設定します。
次の SQL ステートメントを使用してサンプルテーブルを作成します。
app=>
CREATE SCHEMA inventory; CREATE TABLE inventory.products ( id int PRIMARY KEY, product_name text NOT NULL, created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP);次の SQL ステートメントを使用して、サンプルデータをテーブルに入力します。
app=>
INSERT INTO inventory.products (id, product_name) VALUES (1, 'soap'), (2, 'shampoo'), (3, 'conditioner');次の SQL ステートメントを使用して、テーブルにデータが存在することを確認します。
app=>
SELECT count(*) FROM inventory.products;count ------- 3
既存のデータベースで
pgactive
拡張を作成します。app=>
CREATE EXTENSION pgactive;以下のコマンドを使用して pgactive グループを作成して初期化します。
app=>
SELECT pgactive.pgactive_create_group( node_name :='node1-app'
, node_dsn := 'dbname=app
host=firstinstance.111122223333
.aws-region
.rds.amazonaws.com user=master username
password=PASSWORD
');node1-app は、
pgactive
グループ内のノードを一意に識別するために割り当てる名前です。注記
パブリックにアクセス可能な DB インスタンスで、このステップを正常に実行するには、
rds.custom_dns_resolution
パラメータを1
に設定して有効にする必要があります。DB インスタンスの準備が整っているかどうかを確認するには、次のコマンドを使用します。
app=>
SELECT pgactive.pgactive_wait_for_node_ready();コマンドが正常に完了した場合は、次の出力が表示されます。
pgactive_wait_for_node_ready ------------------------------ (1 row)
2 番目の RDS for PostgreSQL インスタンスを設定して pgactive
グループに参加させるには
次の例は、RDS for PostgreSQL DB インスタンスを pgactive
グループに参加させる方法と、DB インスタンスに pgactive
拡張を作成するために必要なその他のステップを示しています。
次の手順では、RDS for PostgreSQL DB インスタンスが pgactive
拡張を使用して設定されていることを前提としています。詳細については、「pgactive 拡張機能の初期化」を参照してください。
psql
を使用して、パブリッシャーから更新を受け取るインスタンスに接続します。psql --host=
secondinstance.111122223333
.aws-region
.rds.amazonaws.com --port=5432 --username=master username
--password --dbname=postgres
次のコマンドを使用して、2 番目の RDS for PostgreSQL DB インスタンスにデータベースを作成します。
postgres=>
CREATE DATABASEapp
;次のコマンドを使用して、接続先を新しいデータベースに切り替えます。
\c
app
既存のデータベースに
pgactive
拡張を作成します。app=>
CREATE EXTENSION pgactive;次に示すように、RDS for PostgreSQL の 2 番目の DB インスタンスを
pgactive
グループに参加させます。app=>
SELECT pgactive.pgactive_join_group( node_name :='node2-app'
, node_dsn := 'dbname=app
host=secondinstance.111122223333
.aws-region
.rds.amazonaws.com user=master username
password=PASSWORD
', join_using_dsn := 'dbname=app
host=firstinstance.111122223333
.aws-region
.rds.amazonaws.com user=postgres
password=PASSWORD
');node2-app は、
pgactive
グループ内のノードを一意に識別するために割り当てる名前です。DB インスタンスの準備が整っているかどうかを確認するには、次のコマンドを使用します。
app=>
SELECT pgactive.pgactive_wait_for_node_ready();コマンドが正常に完了すると、次の出力が表示されます。
pgactive_wait_for_node_ready ------------------------------ (1 row)
最初の RDS for PostgreSQL データベースが比較的大きい場合は、
pgactive.pgactive_wait_for_node_ready()
から復元操作の進行状況レポートを出力されることを確認できます。出力は次の例のようになります:NOTICE: restoring database 'app', 6% of 7483 MB complete NOTICE: restoring database 'app', 42% of 7483 MB complete NOTICE: restoring database 'app', 77% of 7483 MB complete NOTICE: restoring database 'app', 98% of 7483 MB complete NOTICE: successfully restored database 'app' from node node1-app in 00:04:12.274956 pgactive_wait_for_node_ready ------------------------------ (1 row)
この時点から、
pgactive
は 2 つの DB インスタンス間でデータを同期します。次のコマンドを使用して、2 番目の DB インスタンスのデータベースにデータがあるかどうかを確認できます。
app=>
SELECT count(*) FROM inventory.products;データが正常に同期されると、次の出力が表示されます。
count ------- 3
次のコマンドを実行して新しい値を挿入します。
app=>
INSERT INTO inventory.products (id, product_name) VALUES ('lotion');最初の DB インスタンスのデータベースに接続し、次のクエリを実行します。
app=>
SELECT count(*) FROM inventory.products;アクティブ/アクティブレプリケーションが初期化されると、出力は次のようになります。
count ------- 4
pgactive
グループから DB インスタンスをデタッチして削除するには
pgactive
グループから DB インスタンスをデタッチして削除するには、次の手順に従います。
次のコマンドを使用して、最初のインスタンスから 2 番目の DB インスタンスをデタッチできます。
app=>
SELECT * FROM pgactive.pgactive_detach_nodes(ARRAY[‘node2-app
']);次のコマンドを使用して、2 番目の DB インスタンスから
pgactive
拡張を削除します。app=>
SELECT * FROM pgactive.pgactive_remove();拡張を強制的に削除するには
app=>
SELECT * FROM pgactive.pgactive_remove(true);次のコマンドを使用して拡張をドロップします。
app=>
DROP EXTENSION pgactive;
アクティブ/アクティブレプリケーションの競合の処理
pgactive
拡張は、クラスターごとではなく、データベースごとに機能します。pgactive
を使用する各 DB インスタンスは、独立したインスタンスであり、あらゆるソースからのデータ変更を受け入れることができます。変更が DB インスタンスに送信されると、PostgreSQL は変更をローカルにコミットし、pgactive
を使用して他の DB インスタンスに非同期に変更をレプリケートします。2 つの PostgreSQL DB インスタンスが同じレコードをほぼ同時に更新すると、競合が発生する可能性があります。
pgactive
拡張は、競合の検出と自動解決のためのメカニズムを提供します。両方の DB インスタンスでトランザクションがコミットされた時点のタイムスタンプを追跡し、最新のタイムスタンプで変更を自動的に適用します。また、pgactive
拡張は、pgactive.pgactive_conflict_history
テーブルで競合が発生した場合もログに記録します。
pgactive.pgactive_conflict_history
は継続的に増大します。パージポリシーを定義するとよいでしょう。これを行うには、一部のレコードを定期的に削除するか、この関係のパーティションスキームを定義します (その後で対象のパーティションをデタッチ、ドロップ、切り捨てることができます)。パージポリシーを定期的に実装するには、 pg_cron
拡張機能を使用するというオプションがあります。pg_cron
履歴テーブルの例については、「PostgreSQL pg_cron 拡張機能を使用したメンテナンスのスケジュール」の次の情報を参照してください。
アクティブ/アクティブレプリケーションでのシーケンスの処理
pgactive
拡張を使用した RDS for PostgreSQL DB インスタンスは、2 つの異なるシーケンスメカニズムを使用して固有の値を生成します。
グローバルシーケンス
グローバルシーケンスを使用するには、CREATE SEQUENCE
ステートメントを使用してローカルシーケンスを作成します。usingnextval(seqname)
の代わりに pgactive.pgactive_snowflake_id_nextval(seqname)
を使用すると、シーケンスの次の固有な値を取得できます。
次の例では、グローバルシーケンスを作成します。
postgres=>
CREATE TABLE gstest ( id bigint primary key, parrot text );
postgres=>
CREATE SEQUENCE gstest_id_seq OWNED BY gstest.id;
postgres=>
ALTER TABLE gstest \ ALTER COLUMN id SET DEFAULT \ pgactive.pgactive_snowflake_id_nextval('gstest_id_seq');
分割シーケンス
分割ステップまたは分割シーケンスでは、通常の PostgreSQL シーケンスをノードごとに使用します。各シーケンスは同じ量ずつインクリメントされ、異なるオフセットから始まります。例えば、ステップ 100 の場合、ノード 1 は 101、201、301 などとしてシーケンスを生成し、ノード 2 は 102、202、302 などとしてシーケンスを生成します。このスキームは、ノードが長時間通信できない場合でも適切に機能しますが、設計者はスキーマを確立するときに最大ノード数を指定する必要があり、ノードごとの設定が必要になります。間違えると、シーケンスが重複しやすくなります。
次に示すように、ノードで目的のシーケンスを作成することで、このアプローチを pgactive
で比較的簡単に設定できます。
CREATE TABLE some_table (generated_value bigint primary key);
postgres=>
CREATE SEQUENCE some_seq INCREMENT 100 OWNED BY some_table.generated_value;
postgres=>
ALTER TABLE some_table ALTER COLUMN generated_value SET DEFAULT nextval('some_seq');
次に、各ノードで setval
を呼び出して、次のように異なるオフセットの開始値を指定します。
postgres=>
-- On node 1 SELECT setval('some_seq', 1); -- On node 2 SELECT setval('some_seq', 2);
pgactive 拡張のパラメータリファレンス
次のクエリを使用すると、pgactive
拡張に関連するすべてのパラメータを表示できます。
postgres=>
SELECT * FROM pg_settings WHERE name LIKE 'pgactive.%';
pgactive メンバー間のレプリケーションラグの測定
次のクエリを使用して、pgactive
メンバー間のレプリケーションラグを表示できます。全体像を把握するには、すべての pgactive
ノードでこのクエリを実行します。
postgres=# SELECT *, (last_applied_xact_at - last_applied_xact_committs) AS lag FROM pgactive.pgactive_node_slots;
-{ RECORD 1 ]----------------+-----------------------------------------------------------------
node_name | node2-app
slot_name | pgactive_5_7332551165694385385_0_5__
slot_restart_lsn | 0/1A898A8
slot_confirmed_lsn | 0/1A898E0
walsender_active | t
walsender_pid | 69022
sent_lsn | 0/1A898E0
write_lsn | 0/1A898E0
flush_lsn | 0/1A898E0
replay_lsn | 0/1A898E0
last_sent_xact_id | 746
last_sent_xact_committs | 2024-02-06 18:04:22.430376+00
last_sent_xact_at | 2024-02-06 18:04:22.431359+00
last_applied_xact_id | 746
last_applied_xact_committs | 2024-02-06 18:04:22.430376+00
last_applied_xact_at | 2024-02-06 18:04:52.452465+00
lag | 00:00:30.022089
pgactive 拡張の制限事項
すべてのテーブルには主キーが必要です。主キーがないと、更新や削除は許可されません。主キー列の値は更新しないでください。
シーケンスにはギャップがある場合があり、順序に従わないこともあります。シーケンスはレプリケートされません。詳細については、「アクティブ/アクティブレプリケーションでのシーケンスの処理」を参照してください。
DDL とラージオブジェクトはレプリケートされません。
セカンダリの一意のインデックスはデータの相違を引き起こす可能性があります。
照合順序はグループ内のすべてのノードで同一である必要があります。
ノード間の負荷分散はアンチパターンです。
トランザクションが大きいと、レプリケーションの遅延が発生する可能性があります。