PostgreSQLのレプリケーション機能を利用する事になり、
ドキュメントを解読していたのだけど、これがまたややこしい。
公式文書では、データの同期/非同期を含め様々なパターンが紹介されているが、
色々とややこしいので、今回はWALログを使ったレプリケーションについて細かく書いてみる。
色々な記事を漁ってみるとこの方法がスタンダードとして使われている感じ
ここでは、1台のマスタサーバ(プライマリサーバ)と1台のスレーブサーバで構成し、
マスタとスレーブに構築されるデータはできる限り同じになるようにする。
スレーブはマスタからWALデータを待ち受ける状態で起動され、
受け取ったWALデータを自身にリストアを継続的に繰り返す事により、
マスタとスレーブのデータ一貫性を保つ。
WALをスレーブへ転送するタイミングにより方式があり、
wal_keep_segments?ごとに同期を行う方式をシッピングと呼ぶ。
マスタでトランザクションがコミットされる度に、
スレーブへWAL同期を行う方式をストリーミングと呼ぶ。
+-------+
| Query |
+-------+
|
| Request/Response
|
+--------+ +-------+
| Master |---WAL--->| Slave |
+--------+ +-------+
* "Master"は読み書き可能
* "Slave"は読み取り専用(ホットスタンバイ)
レプリケーションではサーバとして利用するOSや
PostgreSQLのバージョンは合わせる必要があります。
公式文書によると、以下の場合動作不可と明記されている。
- OSの違い(LinuxとWindows)
- アーキテクチャの違い(32bit,64bit)
また、以下の場合でも動作する可能性はあるが公式サポートはされないとある。
- PostgreSQLバージョンの違い
上記構成の中で、ユーザから問い合わせを受け取ってから、
その結果をユーザへレスポンスするタイミングによりいくつかの方式がある。
この方式はpostgresql.conf
で設定する事ができる(詳細は後述)。
同期方式[synchronous_commit = on]
マスタと1台のスレーブのディスクへWALを書き込み後にユーザにレスポンスする
メモリ同期[synchronous_commit = remote_write]
マスタのディスクと1台のスレーブのメモリへ
WALを書き込み後にユーザにレスポンスする
スレーブ非同期[synchronous_commit = local]
マスタのディスクへWALを書き込み後に
ユーザへレスポンスする(スレーブへの書き込みは確認しない)
完全非同期[synchronous_commit = off]
マスタ・スレーブ共にWAL書き込みを待たずに
ユーザにレスポンスをする(WALがマスタのメモリに来るまで)
スレーブがマスタのWALデータを読み取る際に遅延が発生した場合、
スレーブが読み取りを行う前にマスタ側でWALの削除が行われる場合がある。
いざスレーブがWAL読み取りを行おうとした時に、
WALデータの不整合によるエラーが出力され、
再度ベースバックアップで基準を揃える必要が出てくる。
FATAL: requested WAL segment XXXXXXX has already been removed
この挙動を避ける為に以下の方法がある。
WALアーカイブモードを有効にする
WALアーカイブモードを有効にする事でスレーブは
WALアーカイブからリストアを行い、レプリケーションを継続することができる。
wal_keep_segmentsを十分な値にする
マスタでWALの回収(削除)が行われるまでの WALデータの容量を十分な値で設定する。
ここからは実際にマスタのレプリケーション環境構築を記述する。
PostgreSQLはマスタ・スレーブ共に9.3.5をソースコードからインストールしている。
ディストリはCentOS6.5
レプリケーション用ユーザの作成
レプリケーションはWALデータへのアクセスを行う為、
レプリケーション専用のユーザで行う方がセキュリティ的に安全です$ psql -U postgres postgres=# create user repl_user replication password 'postgres';
postgresql.confの設定
$ vim postgresql.conf + wal_level = hot_standby + synchronous_commit = on + max_wal_senders = 2 + synchronous_standby_names = 'repl_slave'
wal_level
WALへどのような情報が書き込まれるかを設定する。
ここではWALの情報をレプリケーションに対応させている。synchronous_commit
ユーザにレスポンスを返すタイミングを同期方式で指定する。
ここではスレーブのディスク上にWALが書き込まれてから レスポンスを返す同期方式を指定する。max_wal_senders
スレーブからの同時接続数の上限。
スレーブは1台だがスレーブ台数+1が推奨らしいが詳細不明。synchronous_standby_names
スレーブの参照名をリストで指定する。
ここではスレーブは1台なので文字列をそのまま設定。
pg_hba.confの設定
レプリケーション用ユーザからのアクセスを許可
$ vim pg_hba.conf + host replication repl_user 127.0.0.1/32 md5 + host replication repl_user 192.168.1.0/24 md5
ここまででマスタを再起動したらOK。
ベースバックアップの取得
マスタとスレーブでデータの基準を揃える為に、 ベースバックアップを行う。
ベースバックアップを行うと、マスタのデータディレクトリごと スレーブへコピーされるので、
スレーブ側でinitdb等する必要はない。$ pg_basebackup -h [マスタサーバIP] -U repl_user -p 5432 -D [データディレクトリ] --xlog --progress --verbose
postgresql.confの設定
$ vim postgresql.conf + hot_standby = on
recovery.confの設定
スレーブ用の設定ファイルを作成する。
postgresql.confと同じディレクトリに配置する。$ vim recovery.conf + standby_mode = 'on' + primary_conninfo = 'host=[マスタサーバIP] port=5432 user=repl_user password=postgres application_name=repl_slave'
standby_mode
ホットスタンバイで稼働させるかどうかを設定する。
'on'にするとスレーブ側で参照問い合わせを処理できる。primary_conninfo
ストリーミングレプリケーションを利用する設定。
マスタの接続情報を設定することでストリーミングで稼働する。
WALの転送タイミングがトランザクションのコミット時になる?
ここまででスレーブを起動したらOK。
とりあえず備忘録程度に書きなぐったので読みづらい。
最後にWALログレプリケーションについてまとめる。
- レプリケーションはWALを同期してデータの一貫性を保つ
- マスタとスレーブ側でレプリケーションの基準をベースバックアップで揃える
- WALの同期方式にはシッピングとストリーミングがある
(シッピングはwal_keep_segments分のWALをまとめて同期、
ストリーミングはトランザクションのコミット時に即座に同期する)