MySQLユーザー目線で設定するPostgreSQLのレプリケーション設定
こんにちは。
開発チームのワイルド担当、まんだいです。
PostgreSQL9.4で同期レプリケーションを利用する際の設定に関してまとめます。
弊社では普段MySQLを利用する事が多い状況でのPostgreSQL利用ということで
同じRDBMSとはいえど、戸惑いもありつつの作業でした。
思いの外、素直に動いてくれてとても気分が良かったので
皆さんも使ってみてはいかがでしょうかという感じでまとめてみたいと思います。
今回は少し作業工程が長く複雑ですので、お品書きをさらしておきます。
PostgreSQLのレプリケーション (マスターDB側の作業)
以上の手順で進めたいと思います。
PostgreSQLのレプリケーション (マスターDB側の作業)
今回は既に絶賛稼働中のDBに対してレプリケーションを設定していくという
まさにワイルドな状況で作業を進めました。
余談ですが、こういう状況の方が、かえって燃えますね。
大まかな作業としては
という形になるかと思います。
想定として、ローカルネットワーク内のマスターDBには192.168.1.1、スレーブDBには192.168.1.2のIPアドレスが振られているという事にします。
レプリケーションユーザーを作成する
まずは簡単なところから、レプリケーション用にrepl_userというユーザーの作成を行います。
マスターDBにログインした後、以下のクエリでユーザーを作成します。
CREATE USER repl_user REPLICATION PASSWORD '[パスワード]';
pg_hba.confへの追記
続いて、pg_hba.confの編集を行います。
ここでは、スレーブDBから先ほど作成したrepl_userユーザーを使って作業ができるようにします。
host replication repl_user 192.168.1.2/32 md5
IPアドレスはスレーブのものに変更します。
IPマスクは複数台のスレーブDBを作成する場合はそれなりにIPマスクをいじる必要もありますが
1台のみの場合は/32で問題ないかと思います。
postgresql.confの編集
続いて、postgresql.confの編集に移ります。
ここでは、レプリケーションに関する設定を追加・変更していきます。
必要な設定項目は、全てコメントアウトされているので、アンコメントする事で項目を有効化できます。
この辺はMySQLよりも親切ですね。
レプリケーションのために必要な設定項目は以下のものになります。
wal_level
walファイルにどれだけ情報を載せるかの度合いを設定する項目です。
walレベルは3段階あり、minimal、archive、hot_standbyになります。
デフォルトはminimalで、通常の稼働時には、これで問題ありません。
レプリケーションを設定する場合は、archive以上のレベルが必要なので、今回はhot_standbyに設定します。
wal_level = hot_standby
synchronous_commit
トランザクション実行完了後、クライアントにsuccessを返す時、walファイルの書き込み完了を待つかどうかの設定です。
デフォルトはonで、walファイルが書き込まれた後にクライアントへの応答を返します。
offにすると、walファイルへの書き込みが失敗した場合にトランザクションデータの消失が発生し、クライアント側へ通知したステータスとは異なった結果になります。
ただ、データ的には、トランザクション中のデータがなくなるだけで、不整合が起こる訳ではありません。
クライアント側にsuccessを返したけれど、実際はsuccessではないという問題が発生しうるという事です。
クライアント側への応答速度は向上しますが、たまに(そのたまにがどの程度なのかはトランザクションの失敗する程度による)ウソを返すようになるという問題だけのようです(だけなのか?)。
今回はonにしておきます。
synchronous_commit = on
archive_mode
アーカイブモードをonにすると、通常のwal保存領域とは違う領域にwalファイルを保存しておく事ができます。
レプリケーションの遅延が発生した場合、スレーブ側は未適用のwalファイルを順に追いかける事になります。
ただ、デフォルトの保存領域にあるwalファイルのライフサイクルは意外に短いので、長時間の遅延には耐えられません。
そうなると、リカバリできないほどの遅延が発生した場合は、データの再投入をする必要があり、運用に手間が掛かります。
それを解決するために、デフォルトの保存領域外にwalファイルをコピーする事で、ライフサイクルに左右されず、長時間のレプリケーション遅延に対応できるようにします。
コピーされたwalファイルですが、溜まり続けるという事はない(遅延が発生した場合は残り続けるので要注意)ので、別途バッチでrmする必要はありません。
今回はonにしておきます。
archive_mode = on
archive_command
archive_mode = onの場合、walファイルを保存するためのコマンドを設定します。通常cpコマンドで対応する事になるかと思います。
コマンド内で使える、コピー元のwalファイルを示す置換用文字列が幾つかありますので、それを使います。
- %f ・・・ walファイルのファイル名
- %p ・・・ 作業対象のwalファイルの絶対パス
archive_command = '[walファイルを保存するためのコンソールコマンド]'
max_wal_senders
接続するスレーブDBの数を設定します。
pg_basebackupコマンド経由の接続用にスレーブDBの数 + 1とする事が多いようです。
max_wal_senders = 2 # slaveの数+1
synchronous_standby_names
スレーブとして接続するDB名を列挙します。
ここに記載がない名前を持つスレーブとの接続はできないようになっています。
synchronous_standby_names = "db_slave1" # 複数スレーブを持つ場合はカンマ区切りでDB名を追加
マスターDBの再起動
マスターDB側の設定は以上です。
スレーブ側の設定もこちらでやってしまう事も可能(理由は後述)ですが、postgresql.confが分かりづらくなってしまうので、今回は都度設定していくことにします。
この時点でPostgreSQLを再起動し、設定を反映します。
余談ですが、PostgreSQLの起動コマンドで調べてみると、色々な起動の仕方をされている方がいますが、インストール方法の違いなどで動かない事もあるようです。
私がいつも起動に使っているコマンドは以下のものになります。
# initd経由 /etc/init.d/postgresql-9.4 [start|stop|restart] # pg_ctl経由 su postgres -c "/usr/pgsql-9.4/bin/pg_ctl [start|stop|restart] -D /var/lib/pgsql/9.4/data -m fast"
どちらもrootで実行する必要がありますが、yumでインストールしたPostgreSQLで動作しました。
pg_ctl経由の場合、$PGDATAの場所も指定できるので、PostgreSQLを2プロセス立ち上げる場合
はpg_ctlを使う必要があります。
スレーブDB側の作業
スレーブ側の設定を進めていきます。
スレーブDBサーバーにPostgreSQLがインストールされている前提で話を進めます。
また、バージョンの差異もないものとして進めます。
pg_basebackupでマスターをコピーする
まず、pg_basebackupでマスターのデータ一式をコピーします。
$PGDATAの場所をデフォルト位置と異なる場所にコピーを取る事もできますが、その場合、initd経由で起動する場合、/etc/init.d/postgresqlスクリプト内の$PGDATAのパスを変更する必要があります。
今回は、デフォルトの/var/lib/pgsql/9.4/dataにコピーを取ることにします。
既にある、dataディレクトリをリネームして、退避しておきます。
マスターからデータをコピーするpg_basebackupコマンドは以下のようになります。
pg_basebackup -h 192.168.1.1 -U repl_user -D /var/lib/pgsql/9.4/data -P --xlog
DBのサイズにもよりますが、しばらく待っているとコピーが完了します。
コピーしたdataディレクトリに入ってみると、pg_hba.confやpostgresql.confもコピーされている事に気づきますね。
マスターDB側のpostgresql.confの編集の項で触れた、スレーブ側の設定もマスター側で可能というのは、マスター側のpostgresql.confがコピーされるからというのが理由です。
マスターDBとして稼働するDBはスレーブDBとして稼働するために必要な設定項目を読み飛ばし、スレーブDBとして稼働するDBは、マスターDBとして稼働するために必要な設定項目を読み飛ばすので、うまくできているなと思います。
postgresql.confの編集(スレーブ側)
postgresql.confにスレーブ用の設定を行います。
hot_standby
PostgreSQLをホットスタンバイモードで稼働させるための設定項目です。
ホットスタンバイモードで稼働しているサーバーは、更新系の処理が一切できなくなり、読み取り専用のDBになります。
ただ、この項目単独でレプリケーションが成立する訳ではなく、hot_standbyがonかつ、この後作成するrecovery.confが存在するというのが同時に満たされた場合にレプリケーション機能が有効になります。
hot_standby = on
recovery.confの作成
このファイルは一から作る必要はなく、サンプルが存在するので、それをコピーしてきて手直しします。
recovery.confのサンプルは、/usr/pgsql-9.4/share 以下にありますので、/var/lib/pgsql/9.4/data にコピーします。
cp /usr/pgsql-9.4/share/recovery.conf.sample /var/lib/pgsql/9.4/data/recovery.conf
recovery.confの編集
recovery.conf内で編集する箇所は2箇所です。
これが終わったらレプリケーションに関する設定は完了です!
standby_mode
standby_modeをonにする事で、最後のwalファイルを受け取って処理が完了しても、次のwalファイル待ちの状態で稼働し続けます。
standby_mode = on
primary_conninfo
マスターDBへ接続するための情報を記載します。
特に注意する点は、application_nameの部分がマスターDBのpostgresql.confのsynchronous_standby_namesに列挙された名前に含まれているかという点です。
これ以外は、読んだままという感じです。
primary_conninfo = 'host=192.168.1.1 port=5432 user=repl_user password=[パスワード] application_name=db_slave1'
スレーブDBの再起動からレプリケーションの確認まで
以上の設定が終わったら、準備ができましたのでスレーブDBを再起動します。
再起動のコマンドは、マスターDBと同様です。
再起動が完了したら、レプリケーションが行われている状況になっているはずなので、マスターDB側からレプリケーションの進捗状況を確認します。
マスターDBにログインし、以下のクエリを実行します。
select * from pg_stat_replication; -[ RECORD 1 ]----+------------------------------ pid | 12345 usesysid | 12345 usename | repl_user application_name | db_slave1 client_addr | 192.168.1.2 client_hostname | client_port | 43210 backend_start | 2016-06-12 17:01:07.923879+09 backend_xmin | state | streaming sent_location | 27/B4EED5F8 write_location | 27/B4EED5F8 flush_location | 27/B4EED5F8 replay_location | 27/B4EED5C0 sync_priority | 0 sync_state | async
stateの項目がstreamingになっていれば、ひとまずレプリケーションは実行されているという事になります。
どこまでデータの同期が取れているかは、sent_location、 write_location、 flush_location、 replay_locationで状況がわかります。
- sent_locationは、マスターDBからスレーブDBへどこまでWALファイルが送信されたかを表すアドレスです。
- write_locationは、スレーブ側のバッファ領域にどこまで書き込んだかを表すアドレスです。
- flush_locationは、スレーブ側のディスク領域にどこまで書き込んだかを表すアドレスです。
- replay_locationはスレーブDBでどこまでデータの取り込みが終わったかを表すアドレスです。
4つのアドレスはデータと共に増加していくので、進み具合は一目瞭然となります。
上記の例では、sent_location、 write_location、 flush_locationまでのアドレスは同じなので、ここまでは最新の状態になっている事を表します。
replay_locationが若干遅れていますが、現在は非同期モードでの実行になるので、大幅にずれていなければ気にはならないところです。
以上です。