pg_rewindとは
Streaming Replicationを使ってマスタ-スタンバイ構成のPostgreSQLを運用している場合、フェイルオーバやスイッチオーバが発生してマスタが切り替わった後に、古いマスタを再度組み込む際に役立つコマンドです。
百聞は一見に如かず。
レッツトライ。
Streaming Replication構成の作成
1号機の設定
postgresql.confに以下を記載します。
pg_rewindのためにwal_log_hints
を有効にしておきます。データチェックサム有効で代用できるみたいですが今回はこれで。
listen_addresses = '*'
wal_level = hot_standby
max_wal_senders = 3
wal_keep_segments = 30
max_replication_slots = 3
hot_standby = on
logging_collector = on
log_line_prefix = '[%m]'
wal_log_hints = on
pg_hba.confに1号機、2号機間でpg_basebackupで接続できるように設定します。
また、pg_rewindを実行するために、replication権限でないスーパーユーザによる通常の接続も許可しておきます。
host postgres postgres 192.168.56.101/32 trust
host postgres postgres 192.168.56.102/32 trust
host replication postgres 192.168.56.101/32 trust
host replication postgres 192.168.56.102/32 trust
PostgreSQLを起動して、レプリケーション・スロットを作成します。
$ pg_ctl start
$ psql
psql (9.5.0)
Type "help" for help.
postgres=# SELECT * FROM pg_create_physical_replication_slot('slave_slot');
slot_name | xlog_position
------------+---------------
slave_slot |
(1 row)
2号機の設定
pg_basebackupでデータをコピーします。
$ pg_basebackup -h 192.168.56.102 -D 9.5
NOTICE: pg_stop_backup complete, all required WAL segments have been archived
スタンバイとして起動するために、recovery.confを作成します。
$ cp /usr/local/pgsql/9.5/share/recovery.conf.sample recovery.conf
以下を記載します。
standby_mode = on
primary_conninfo = 'host=192.168.56.102 application_name=slave1'
primary_slot_name = 'slave_slot'
PostgreSQLを起動します。これで非同期レプリケーション構成になります。
$ pg_ctl start
同期レプリケーション設定
1号機にてpostgresql.confに以下を追記します。
synchronous_standby_names = 'slave1'
設定ファイルを更新すれば、同期レプリケーション構成になります。
$ pg_ctl reload
$ psql
psql (9.5.0)
Type "help" for help.
postgres=# SELECT * FROM pg_stat_replication ;
-[ RECORD 1 ]----+------------------------------
pid | 4905
usesysid | 10
usename | postgres
application_name | slave1
client_addr | 192.168.56.101
client_hostname |
client_port | 44976
backend_start | 2016-01-30 22:26:49.279467+09
backend_xmin |
state | streaming
sent_location | 0/3000220
write_location | 0/3000220
flush_location | 0/3000220
replay_location | 0/3000220
sync_priority | 1
sync_state | sync
フェイルオーバ発生
pg_rewindを使う状況にするため、1号機から2号機にフェイルオーバさせます。
1号機のPostgreSQLをシャットダウン。
$ pg_ctl stop
waiting for server to shut down.... done
server stopped
2号機をマスタに昇格させます。
$ pg_ctl promote
server promoting
1号機のクラスタ再組み込み
pg_rewindを使わない場合、pg_basebackupで2号機からデータを全コピーする必要がありました。
つまり、新しくスタンバイ機を作成する手順と同一です。
しかし、1号機にはもともとマスタとして動作していた時のデータが残っています。これを流用して、2号機にスタンバイとして追随するために必要なデータだけを取ってきてくれるのがpg_rewindです。
データベースのサイズが大きい場合、全データをコピーするpg_basebackupに比べて格段に効率的で時間も短く済みます。
正常停止後のデータベースに対してpg_rewindを実行します。
ちなみに、-n
オプションをつけるとドライランになるので、これでオプションが正しく設定できているか確かめると便利です。
$ pg_rewind -D pg_data/9.5/ --source-server="host=192.168.56.101"
servers diverged at WAL position 0/3000220 on timeline 1
rewinding from last common checkpoint at 0/3000178 on timeline 1
Done!
あとは、recovery.conを作って、PostgreSQLを起動して、同期レプリケーション構成にするだけです。
ハマリどころ
pg_rewindはreplication権限以外に、スーパユーザによる通常の接続権限も要求する
$ pg_rewind -D pg_data/9.5/ --source-server="host=192.168.56.101"
could not connect to server: FATAL: no pg_hba.conf entry for host "192.168.56.102", user "postgres", database "postgres"
Failure, exiting
pg_hba.confに忘れず設定しておきましょう。
旧マスタのデータベースは正常停止しておく必要がある
Streaming ReplicationによるHAクラスタを組んでいる場合、フェイルオーバ発生時、旧マスタはimmediateモードで停止している場合が多いと思います。
その状態でpg_rewindを実行しても以下のようなメッセージが出て失敗します。
$ pg_rewind -D pg_data/9.5/ --source-server="host=192.168.56.101"
target server must be shut down cleanly
Failure, exiting
そのため、一度PostgreSQLを起動して正常停止させます。
$ pg_ctl start
$ pg_ctl stop
レプリケーション・スロットは新たに作成しなおす必要がある
これは、pg_rewindには直接関係ないです。
というかレプリケーション・スロットの仕様なので、pg_basebackupを使って新たにスタンバイを組み込む場合も同じです。
レプリケーション・スロットを使っている場合、新しいマスタにはスロットが存在していないので、再度作成する必要があります。
postgresql.confをシンボリックリンクで運用している場合、一度リンクを削除する必要がある
同期・非同期レプリケーションの切り替えにsynchronous_standby_names
を設定したファイルとしていないファイルを両方用意して、postgresql.confというシンボリックリンクでどちらを利用するか切り替えるような運用をしている場合、pg_rewindが以下のようなエラーを吐きます。
$ pg_rewind -D pg_data/9.5/ --source-server="host=192.168.56.101" -n
servers diverged at WAL position 0/E000060 on timeline 5
rewinding from last common checkpoint at 0/D000060 on timeline 5
"pg_data/9.5//postgresql.conf" is not a regular file
Failure, exiting
pg_rewind対象の停止済みのデータベース領域から一度シンボリックリンクを削除してあげれば大丈夫です。スタンバイ再組み込みの時にどのみち新たに作成しなおすので問題はないです。
以上!