PostgreSQLは、強力で機能豊富なリレーショナルデータベース管理システム(RDBMS)です。これは無料でオープンソースであり、1996年から開発されています。Postgresはデータをアーカイブおよび複製するさまざまな方法を提供しており、その1つがストリーミング複製です。このモードでは、プライマリ(マスター)インスタンスがメインのアクティブなデータベースを処理し、操作を実行します。セカンダリ(スレーブ)インスタンスは、アクティブデータベースの同一のコピーを維持しながら、プライマリからすべての変更をコピーします。セカンダリサーバーは、読み取り専用クエリも受け入れることができます。プライマリに障害が発生した場合、セカンダリサーバーはスタンバイモードを終了し、新しいマスターとして動作できます(これはフェイルオーバーと呼ばれます)。
PostgreSQLレプリケーションは通常、ログ先行書き込み(WAL)に依存しています。これは、データの変更をディスクに書き込む前にログに記録するプロセスです。これらのWALレコードは、ファイルとして2番目のノードにコピーされるか(ファイルベースのログ配布)、ノード間で直接ストリーミングされます(ストリーミングレプリケーション)。ほとんどの場合、後者は、マスターノードでの変更がスタンバイノードによって受信されるまでの遅延を減らします。
ファイルベースのログ配布なしでストリーミングレプリケーションを使用する場合の問題は、プライマリがWALレコードをすぐに破棄すると、セカンダリサーバーが一部のWALレコードを見逃す可能性があることです。多くの構成パラメーターでこのリスクを軽減できますが、多くの場合、不要なストレージコストが発生します。解決策はレプリケーションスロットです。これはPostgresが提供する機能であり、プライマリサーバーがスタンバイノードで受信された後にのみWALレコードを破棄するようにします。
2つのDebian10ノードにレプリケーションスロットを備えたストリーミングレプリケーションを設定します。
- 2つの同一のDebian10インスタンス。
- 両方のインスタンスへのrootアクセス。
- $EDITOR環境変数は両方のインスタンスで設定する必要があります。
ステップ1:PostgreSQLのインストール
両方のノードを更新して再起動します:
apt update apt upgrade -y reboot
両方のノードにPostgresをインストールし、PostgreSQLが有効で実行されていることを確認します。
apt install -y postgresql systemctl enable --now [email protected]
注:PostgreSQLを更新する場合、ドキュメントによると、スタンバイを最初に更新する方が安全なオプションです。
ステップ2:初期構成
デフォルトでは、PostgreSQLはループバックインターフェイスでのみリッスンし、外部からアクセスすることはできません。 postgresql.confを編集して、両方のノードのリッスンアドレスを変更します。
$EDITOR /etc/postgresql/11/main/postgresql.conf
次の行を見つけます:
#listen_addresses = 'localhost'
次のように変更します:
listen_addresses = 'node_ip_address,127.0.0.1'
両方のノードが同じローカルネットワークを共有している場合は、node_ip_addressにプライベートアドレスを使用できますが、Postgresはインターネットにアクセスできません。それ以外の場合は、パブリックアドレスを使用してください。
変更を保存してから、両方のインスタンスを再起動します。
systemctl restart [email protected]
ステップ3:マスター構成
この手順は、プライマリ/マスターサーバーにのみ関係します。
Postgresターミナルを開きます:
sudo -u postgres psql
スタンバイノードは、ユーザーを使用してマスターに接続します。作成する:
postgres=# CREATE ROLE replicator LOGIN REPLICATION ENCRYPTED PASSWORD 'replicator_password';
次に、レプリケーションスロットを作成して終了します:
postgres=# SELECT * FROM pg_create_physical_replication_slot('replicator'); postgres=# \q
簡単にするために、レプリケーションの役割とスロットは両方とも「レプリケーター」と呼ばれますが、同一である必要はありません。
次に、pg_hba.confにエントリを作成して、レプリケータユーザーがスタンバイからマスターに接続できるようにします。開く:
$EDITOR /etc/postgresql/11/main/pg_hba.conf
最後に次の行を追加します:
host replication replicator standby_ip_address/32 md5
マスターインスタンスを再起動します:
systemctl restart [email protected]
ステップ4:ベースバックアップ
このステップのコマンドは、セカンダリ/スレーブサーバーで実行する必要があります。
まず、セカンダリノードでPostgresを停止します:
systemctl stop [email protected]
古いデータディレクトリをバックアップします:
mv /var/lib/postgresql/11/main/ /var/lib/postgresql/11/main.bak
次のコマンドを使用して、マスターのデータディレクトリをスレーブに複製します。
pg_basebackup -h master_ip_address -U replicator -D /var/lib/postgresql/11/main/ -P --password --slot replicator
パスワードの入力を求められます。マスターでの作成時にレプリケーターロールに選択したパスワードを入力します。転送が完了したら、postgresユーザーにデータディレクトリの所有権を付与します。
chown -R postgres:postgres /var/lib/postgresql/11/main
ステップ5:スタンバイ構成
この手順は、セカンダリ/スレーブサーバーにのみ関係します。
postgresql.confでホットスタンバイモードを有効にします:
$EDITOR /etc/postgresql/11/main/postgresql.conf
次の行を見つけてコメントを外します:
#hot_standby = on
Postgresデータディレクトリにrecovery.confファイルを作成します:
$EDITOR /var/lib/postgresql/11/main/recovery.conf
スタンバイモードを有効にする:
standby_mode = 'on'
マスターで作成された資格情報を使用してレプリケーション接続パラメーターを設定します:
primary_conninfo = 'host=master_ip_address port=5432 user=replicator password=replicator_password'
マスターで作成したレプリケーションスロットの名前を設定します:
primary_slot_name = 'replicator'
フェイルオーバートリガーファイルへのパスを設定します:
trigger_file = '/var/lib/postgresql/11/main/failover.trigger'
trigger_fileパラメーターが設定されている場合、このトリガーファイルが作成されると、Postgresはスタンバイモードを終了し、プライマリサーバーとして通常の操作を開始します。このパラメーターは必須ではありません。
Recovery.confを作成したら、postgresユーザーに所有権を付与します:
chown postgres:postgres /var/lib/postgresql/11/main/recovery.conf
これでPostgresを開始できます:
systemctl start [email protected]
これでスタンバイモードになり、新しいトランザクションを複製する必要があります。
レプリケーションをテストするには、マスターで書き込みアクションを実行します。たとえば、マスター上に新しいデータベースを作成します。
sudo -u postgres psql -c "CREATE DATABASE replitest"
数秒待ってから、スレーブ上のデータベースを一覧表示します。
sudo -u postgres psql -c "\l"
replitestデータベースが実際にスタンバイサーバーによって複製されたことがわかります。
List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+----------+-------------+-------------+----------------------- postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | replitest | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres (4 rows)
注:ここに示すようにフェイルオーバーをテストするには、フェイルオーバー後にスタンバイサーバーをリセットする必要があります。
Postgresはスタンバイモードであるため、フェイルオーバー前にセカンダリノードで書き込み操作を実行できないようにする必要があります。たとえば、次のコマンドを実行します。
sudo -u postgres psql -c "CREATE DATABASE test"
コマンドは失敗するはずです:
ERROR: cannot execute CREATE DATABASE in a read-only transaction
フェイルオーバーを通知するには、recovery.confで指定されたトリガーファイルを作成します
touch /var/lib/postgresql/11/main/failover.trigger
数秒待ってから、書き込み操作を実行してみてください。例:
sudo -u postgres psql -c "CREATE DATABASE test2"
Postgresはスタンバイとして動作しなくなったため、動作は成功します。 Postgresはまた、recovery.confファイルの名前をrecovery.doneに変更し、トリガーファイルを削除します。
スタンバイに戻るには、(以前の)セカンダリノードでPostgresを停止します:
systemctl stop [email protected]
データディレクトリをリセットします:
mv /var/lib/postgresql/11/main/ /var/lib/postgresql/11/main.2.bak pg_basebackup -h master_ip_address -U replicator -D /var/lib/postgresql/11/main/ -P --password --slot replicator chown -R postgres:postgres /var/lib/postgresql/11/main
そして、recovery.confを再作成します:
cp /var/lib/postgresql/11/main.2.bak/recovery.done /var/lib/postgresql/11/main/recovery.conf
最後に、Postgresを再起動します:
systemctl start [email protected]
これで、セカンダリインスタンスはスタンバイモードに戻ります。この時点でレプリケーションを再テストすることをお勧めします。
マスターノード上の不要なデータベースを削除します。例:
sudo -u postgres psql postgres=# DROP DATABASE replitest;
そして、スタンバイノードの古いデータディレクトリを削除します:
rm /var/lib/postgresql/11/main.bak -r rm /var/lib/postgresql/11/main.2.bak -r