PostgreSQL 13.6 ストリーミングレプリケーションによる主従同期の設定方法

はじめに

本番環境でPostgreSQLを利用する場合、単一障害点を防ぐためにプライマリ-スタンバイ構成を構築することが推奨されます。この記事では、PostgreSQL 13.6を使用したストリーミングレプリケーションの設定手順と、フェイルオーバー時の操作を詳しく解説します。

環境の設定

  • PostgreSQLバージョン: 13.6
  • プライマリサーバIP: 192.168.1.10
  • スタンバイサーバIP: 192.168.1.11
  • データディレクトリ: /var/lib/pgsql/data

ストリーミングレプリケーションの設定手順

  1. プライマリサーバでレプリケーションユーザーを作成し、権限を付与する。(あらかじめフェイルオーバー時のアクセス設定をpg_hba.confで構成しておくことを推奨します)
  2. スタンバイサーバにPostgreSQLをインストールする。プライマリサーバと同じバージョンをインストールし、データディレクトリ(pgdata)とアーカイブディレクトリのファイルを削除します。この操作はスタンバイサーバで実行してください。
  3. スタンバイサーバでpg_basebackupコマンドを使用して同期をセットアップする。
  4. スタンバイサーバを起動する。

具体的な操作コマンド

1. プライマリサーバでユーザーを作成し、権限を付与する

postgres=# CREATE ROLE sync_user LOGIN REPLICATION ENCRYPTED PASSWORD 'sync_pass_2024';
CREATE ROLE

2. pg_hba.confを設定し、スタンバイサーバからのアクセスを許可する

$ vim /var/lib/pgsql/data/pg_hba.conf
host    replication     all             192.168.1.10/32         md5
host    replication     all             192.168.1.11/32         md5
postgres=# SELECT pg_reload_conf(); -- 設定ファイルをリロード

3. スタンバイサーバでpg_basebackupを実行して同期をセットアップする

$ pg_basebackup -h 192.168.1.10 -U sync_user -p 5432 -F p -X s -v -P -R -D /var/lib/pgsql/data
Password: 
pg_basebackup: base backup initiated
WARNING:  skipping special file "./.s.PGSQL.5432"
pg_basebackup: write-ahead log start point: 0/30000028 on timeline 1
pg_basebackup: starting background WAL receiver
pg_basebackup: created temporary replication slot "pg_basebackup_12345"
pg_basebackup: base backup completed

4. スタンバイサーバを起動する

$ pg_ctl start -l /var/lib/pgsql/log/startup.log
waiting for server to start.... done
server started

データベースの同期状態を確認する

1. オペレーティングシステムのプロセスを確認する

プライマリサーバにはwalsenderプロセスが追加されます。

$ ps -ef | grep postgres | grep sender
postgres  7854 18709  0 11:19 ?        00:00:00 postgres: walsender sync_user 192.168.1.11(12836) streaming 0/1C0003E0

スタンバイサーバにはwalreceiverプロセスが存在します。

$ ps -ef | grep postgres
postgres  30471     1  0 11:19 ?        00:00:00 /usr/pgsql-13/bin/postgres
postgres  30472 30471  0 11:19 ?        00:00:00 postgres: startup recovering 00000001000000000000001C
postgres  30473 30471  0 11:19 ?        00:00:00 postgres: checkpointer 
postgres  30474 30471  0 11:19 ?        00:00:00 postgres: background writer 
postgres  30475 30471  0 11:19 ?        00:00:00 postgres: stats collector 
postgres  30476 30471  0 11:19 ?        00:00:00 postgres: walreceiver 

2. データベースのシステムビューを確認する

プライマリサーバではpg_is_in_recovery()fを返し、スタンバイサーバではtを返します。

postgres=# SELECT pg_is_in_recovery();
 pg_is_in_recovery 
------------------
 f
(1 row)

postgres=# SELECT pg_is_in_recovery();
 pg_is_in_recovery 
------------------
 t
(1 row)

プライマリサーバでは、pg_stat_replicationビューをクエリしてスタンバイサーバの同期状態を確認できます。

postgres=# \x
Expanded display is on.
postgres=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----------------+------------------------------
pid                        | 7854
usesysid                   | 16436
usename                    | sync_user
application_name           | walreceiver
client_addr                | 192.168.1.11
client_port                | 12836
backend_start              | 2023-12-22 11:19:53.781303+08
state                      | streaming
sent_lsn                   | 0/1C0003E0
write_lsn                  | 0/1C0003E0
flush_lsn                  | 0/1C0003E0
replay_lsn                 | 0/1C0003E0
write_lag                  | 
flush_lag                  | 
replay_lag                 | 
sync_priority              | 0
sync_state                 | async
reply_time                 | 2023-12-22 11:24:24.29878+08

スタンバイサーバではpg_stat_wal_receiverビューで同期状態を確認できます。

postgres=# SELECT * FROM pg_stat_wal_receiver;
-[ RECORD 1 ]----------------+------------------------------
pid                        | 30476
status                     | streaming
receive_start_lsn          | 0/1C000000
receive_start_tli           | 1
written_lsn                | 0/1C0003E0
flushed_lsn                | 0/1C000000
received_tli               | 1
last_msg_send_time          | 2023-12-22 11:32:25.206129+08
last_msg_receipt_time       | 2023-12-22 11:32:25.206617+08
latest_end_lsn             | 0/1C0003E0
latest_end_time            | 2023-12-22 11:19:53.783906+08
sender_host                | 192.168.1.10
sender_port                | 5432
conninfo                   | user=sync_user password=******** channel_binding=disable dbname=replication host=192.168.1.10 port=5432 fallback_application_name=walreceiver sslmode=disable sslcompression=0 ssl_min_protocol_version=TLSv1.2 gssencmode=disable krbsrvname=postgres target_session_attrs=any

pg_stat_replicationの主要なフィールドの説明は以下の通りです。

  • sent_lsn: スタンバイに送信された最後のWAL位置(まだディスクに書き込まれていない)。
  • write_lsn: スタンバイのオペレーティングシステムに書き込まれた最後のWAL位置(まだディスクにフラッシュされていない)。
  • flush_lsn: スタンバイのディスクにフラッシュされた最後のWAL位置。
  • replay_lsn: スタンバイでリプレイされた最後のトランザクションログ位置(ユーザーが見える状態)。

現在のWAL位置はpg_current_wal_lsn()で確認できます。主サーバとスタンバイサーバの遅延は、pg_current_wal_lsn() - replay_lsnで計算できます。

フェイルオーバー(主従切り替え)の手順

  1. プライマリサーバを停止する。
  2. スタンバイサーバでpg_ctl promoteを実行してプライマリに昇格させる。
  3. アプリケーション設定を更新して新しいプライマリ(元スタンバイ)に接続する。(事前にVIPを設定している場合は、VIPを新しいプライマリに切り替える)
  4. 元プライマリサーバにstandby.signalファイルを作成し、postgresql.auto.confを設定して新しいプライマリサーバと同期する。
  5. 元プライマリサーバを起動し、新しいスタンバイサーバとして動作させる。注意: 非同期レプリケーションの場合、プライマリサーバがダウンするとデータ損失が発生する可能性があります。

フェイルオーバーの具体的な操作コマンド

1. プライマリサーバのシミュレーションダウン

$ pg_ctl stop -m immediate
waiting for server to shut down.... done
server stopped

この時点で、スタンバイサーバのpg_stat_wal_receiverには出力がありません。ログには同期エラーの情報が記録されます。

2. スタンバイサーバをプライマリに昇格させる

$ pg_ctl promote
waiting for server to promote.... done
server promoted

データベースログを確認すると、以下の情報が表示されます。

2023-12-22 11:45:44.835 CST [30472] LOG:  received promote request
2023-12-22 11:45:44.835 CST [30472] LOG:  redo done at 0/1C0003A8
2023-12-22 11:45:44.837 CST [30472] LOG:  selected new timeline ID: 2
2023-12-22 11:45:44.883 CST [30472] LOG:  archive recovery complete
2023-12-22 11:45:44.889 CST [30471] LOG:  database system is ready to accept connections

元スタンバイサーバのstandby.signalファイルは自動的に削除されます。

3. 元プライマリサーバを新しいスタンバイサーバにする

データディレクトリに移動します。

$ cd /var/lib/pgsql/data
$ touch standby.signal

4. 新しいプライマリサーバの接続情報を設定する

$ vim postgresql.auto.conf
# Do not edit this file manually!
# It will be overwritten by the ALTER SYSTEM command.
primary_conninfo = 'user=sync_user password=sync_pass_2024 channel_binding=disable host=192.168.1.11 port=5432 sslmode=disable sslcompression=0 ssl_min_protocol_version=TLSv1.2 gssencmode=disable krbsrvname=postgres target_session_attrs=any'

5. 元プライマリサーバ(新しいスタンバイサーバ)を起動する

$ pg_ctl start
$ psql
psql (13.6)
Type "help" for help.

postgres=# \x
Expanded display is on.
postgres=# SELECT * FROM pg_stat_wal_receiver;
-[ RECORD 1 ]----------------+------------------------------
pid                        | 5776
status                     | streaming
receive_start_lsn          | 0/1C000000
receive_start_tli          | 2
written_lsn                | 0/1C0026C8
flushed_lsn                | 0/1C000000
received_tli               | 2
last_msg_send_time         | 2023-12-22 14:21:05.444004+08
last_msg_receipt_time      | 2023-12-22 14:21:05.444451+08
latest_end_lsn             | 0/1C0026C8
latest_end_time            | 2023-12-22 14:20:35.378922+08
sender_host                | 192.168.1.11
sender_port                | 5432
conninfo                   | user=sync_user password=******** channel_binding=disable dbname=replication host=192.168.1.11 port=5432 fallback_application_name=walreceiver sslmode=disable sslcompression=0 ssl_min_protocol_version=TLSv1.2 gssencmode=disable krbsrvname=postgres target_session_attrs=any

タグ: PostgreSQL ストリーミングレプリケーション 高可用性

6月3日 22:02 投稿