読者です 読者をやめる 読者になる 読者になる

PostgreSQL9.4でストリーミングレプリケーションする

概要

PostgreSQL9.4でストリーミングレプリケーションの構成を組んでみる
以下のような構成を作成する

  • マスター1台
  • スレーブ2台

f:id:hkou:20150517181107p:plain

マスターからスレーブに矢印を引いたところに「同期」と「非同期」とあるが、これはWALファイルをマスターからスレーブに転送した時にスレーブに書き込まれてからレスポンスを返す設定とスレーブに書き込まれたかどうか確認せずに即レスポンスを返す設定のことである。
スレーブが複数台ある場合は、全て非同期か、1台のみ同期でそれ以外が非同期しか設定が出来ない仕様になっている。

また、単純なレプリケーションの設定のみではなく以下の設定も記述する

  • マスターが落ちた時のスレーブをマスターに昇格させる設定
  • 落ちたノードに対してリカバリするためにWALアーカイブの設定

環境

AWS EC2インスタンス上に以下のバージョンの環境を構築する。

手順

PostgreSQL9.4のインストール

以下の記事を参照して設定する まずは1台のEC2インスタンスにインストールした後、AMIを抽出してそのイメージを元に2台インスタンスを立ち上げるのが効率的である。

hkou.hatenablog.com

レプリケーション用のユーザーを作成する

DB1でレプリケーション用のユーザーを作成する。
ユーザー名、パスワードは任意の設定でよい。

su - postgres
psql
CREATE USER repl_user REPLICATION PASSWORD 'XXXXX';

マスターとスレーブが接続できるように設定する

DB1のpg_hba.confに接続設定を追加する

vi /var/lib/pgsql/9.4/data/pg_hba.conf

↓記述追加
host replication repl_user 127.0.0.1/32 md5
host replication repl_user 192.168.1.1/32 md5
host replication repl_user 192.168.1.2/32 md5
host replication repl_user 192.168.1.3/32 md5

今の設定だとpostgresユーザーのみでしかpsql接続できないので、他のユーザーでも接続できるように記述を変更する

local   all             all                                     peer
↓
local   all             all                                     trust

これでpostgresユーザー以外でもpostgresユーザとして接続ができるようになる

$ psql -U postgres

psql (9.4.1)
Type "help" for help.

postgres=# 

postgres.confの設定

DB1のpostgres.confを設定する

vi /var/lib/pgsql/9.4/data/postgres.conf

wal_levelをhot_standbyにする

wal_level = hot_standby

レプリケーションの種類を指定する

設定値 意味
on 同期
remote_write メモリ同期
local スレーブ非同期
off 完全非同期
synchronous_commit = on

WALファイルを送信する先の数(スレーブの数)+1に設定する

max_wal_senders = 3 

同期レプリケーションするノードの名前を設定する
スレーブ側にも名前を同様の設定をする必要がある、後述にて説明する。

synchronous_standby_names = 'DB2'

WALファイルを別の場所にアーカイブするモードを有効にする。
デフォルトではWALファイルはPGDATA/pg_xlogディレクトリに保存されるが上限があり古いWALファイルは順次削除されていく
このままだとリカバリするときに必要なWALファイルが足りなくなる可能性があるため別のディレクトリに保存するモードを有効にする必要がある。

archive_mode = on

WALファイルをアーカイブ先のディレクトリにコピーするコマンドを設定する。
本来は物理的に別のドライブに保存する方が好ましいが試験的な環境なのでPGDATAの配下にarchiveディレクトリを作成し、そこにコピーするように設定する。

archive_command = 'cp -i %p /var/lib/pgsql/9.4/archive/%f'

ベースバックアップをスレーブに転送する

マスタのDB情報をスレーブのDB情報と同期させる為、マスターの情報をスレーブにコピーする

DB2(192.168.1.2)で実行

一応元々のデータをバックアップしておく
$ mv /var/lib/pgsql/9.4/data /var/lib/pgsql/9.4/data.bak
$ pg_basebackup -h 192.168.1.1 -U repl_user -D /var/lib/pgsql/9.4/data/ -P --xlog

DB2(192.168.1.3)で実行

一応元々のデータをバックアップしておく
$ mv /var/lib/pgsql/9.4/data /var/lib/pgsql/9.4/data.bak
$ pg_basebackup -h 192.168.1.1 -U repl_user -D /var/lib/pgsql/9.4/data/ -P --xlog

dataディレクトリが生成されたはずだが、一応ls -laして所有者を確認しておく、所有者が「postgres」以外だとPostgreSQLを起動したときにパーミッションエラーで起動が出来ないのでもし違う場合はchownで所有者を「postgres」に変更しておく。

スレーブDBの設定

recovery.confの設定

まずはサンプル用のrecovery.confPGDATAにコピーする。

$ cp /usr/pgsql-9.4/share/recovery.conf.sample /var/lib/pgsql/9.4/data/recovery.conf

コピーしてきたrecovery.confを編集する。 DB2の設定

$ vi /var/lib/pgsql/9.4/data/recovery.conf

standby_mode = on
primary_conninfo = 'host=192.168.1.1 port=5432 user=repl_user password=XXXXX application_name=DB2'

DB3の設定

$ vi /var/lib/pgsql/9.4/data/recovery.conf

standby_mode = on
primary_conninfo = 'host=192.168.1.1 port=5432 user=repl_user password=XXXXX application_name=DB3'

スレーブのpostgres.confの設定

$ vi /var/lib/pgsql/9.4/data/postgres.conf
hot_standby = on

マスターが落ちた時にスレーブをマスターに昇格させる時に使う設定
下記のファイルが生成された瞬間にスレーブはマスターに昇格する、ただしPostgreSQLには生死を判定する機能がないのでpgpoolなどのサードパーティを使って生死判定とトリガーファイルの自動生成を設定する必要がある。

trigger_file = '/tmp/trigger_file'

PostgreSQLを起動する

DB1、DB2、DB3を起動する

$ sudo systemctl start postgresql-9.4

レプリケーションの状態を確認する

マスタ(DB1)上で以下のクエリーを実行し確認する。

$ psql -U postgres

select application_name, client_addr, backend_start, state, sync_state from pg_stat_replication;

設定が正しくされていればDB2とDB3の行が表示されるはず。