Skip to content

Instantly share code, notes, and snippets.

@yukpiz
Last active August 29, 2015 14:28
Show Gist options
  • Save yukpiz/1d8da300fb416bcf0bf8 to your computer and use it in GitHub Desktop.
Save yukpiz/1d8da300fb416bcf0bf8 to your computer and use it in GitHub Desktop.

PostgreSQLにおけるレプリケーションの利用

PostgreSQLのレプリケーション機能を利用する事になり、
ドキュメントを解読していたのだけど、これがまたややこしい。

WALログレプリケーションの概要

公式文書では、データの同期/非同期を含め様々なパターンが紹介されているが、
色々とややこしいので、今回は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バージョンの違い

WAL同期方式

上記構成の中で、ユーザから問い合わせを受け取ってから、
その結果をユーザへレスポンスするタイミングによりいくつかの方式がある。
この方式は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読み取りを行おうとした時に、
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ログレプリケーションについてまとめる。

  1. レプリケーションはWALを同期してデータの一貫性を保つ
  2. マスタとスレーブ側でレプリケーションの基準をベースバックアップで揃える
  3. WALの同期方式にはシッピングとストリーミングがある
    (シッピングはwal_keep_segments分のWALをまとめて同期、
    ストリーミングはトランザクションのコミット時に即座に同期する)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment