Asial Blog

Recruit! Asialで一緒に働きませんか?

PostgreSQLのレプリケーション機能をつかってみた

カテゴリ :
バックエンド(プログラミング)
タグ :
PostgreSQL
レプリケーション
データベース
皆様、ご無沙汰しております。笹亀@イネ花粉に苦しんでます。

昨日(7/10)、最近愛用しているPhpStormを開発しているJetBrainsのエバンジェリストとCEOの方が来日されて、講演をされるとのことで、参加をしてきました。
http://www.zusaar.com/event/844003
内容もよかったのですが、エバンジェリストの方がとてもユニークな方だったのが印象的でした。

さて、本日は少し前から興味を持っていたのですが、中々試す機会がなかった内容です。
今回はPostgreSQLのレプリケーションの設定を解説しながらご紹介をしていきたいと思います。

PostgreSQLのレプリケーションについて


まずは、マスターとスレーブにするサーバへPostgreSQLをインストールしておきます。
インストールするバージョンは必ず9.2以上でインストールしてください。また、インストールはそれぞれの環境でご準備くださいませ。インストール方法については割愛します。(googleさんにお聞きください(笑))

PostgreSQLのレプリケーションだけではなく、マスター側で更新処理(登録・更新・削除など)があった場合にスレーブへ更新情報をやり取りする必要があります。PostgreSQLではその更新のやり取りをWAL(Write Ahead Logging)にて行われます。WALはテーブルに書き込みを行う前に変更情報を記録しているログです。ログにはアンドゥとリドゥ用の情報が含まれていることから、DBMSがクラッシュしたときなどには、クラッシュ直前までリカバリを行うこともできます。

PostgreSQLのレプリケーションでは、WALの同期をさせるタイミングについて、以下の4つの設定することができます。
  1. ■同期
  2.  マスターと1台のスレーブのディスクへのWALを書き込み後にユーザにレスポンスする
  3. ■メモリ同期
  4.  マスタのディスクと1台のスレーブのメモリへのWALを書き込み後にユーザにレスポンスする
  5. ■スレーブ非同期
  6.  マスターのディスクへのWALを書き込み後にユーザにレスポンスする(スレーブへの書き込みは確認しない)
  7. ■完全非同期
  8.  マスター・スレーブともにWAL書き込みを待たずにユーザにレスポンスする(WALはマスターのメモリ上のみ)
スレーブ非同期がMySQLにて弊社でもよく使っているレプリケーションの同期設定です。
今回の設定も「スレーブ非同期」にて設定をしていきます。

レプリケーションの設定(マスター側)


それでは実際にマスター側のPostgreSQLの設定をしていきます!

1.レプリケーションをするためのPostgreのユーザを作成する


psqlコマンドでログインをして、下記のコマンドでユーザをつくります。
  1. CREATE USER repl_user REPLICATION PASSWORD 'xxx';


2.postgres.confにマスターの設定を追加する


postgresql.confはPostgreSQLデータフォルダ内にあります。
エディターでファイルを開いて更新します。
  1. wal_level = hot_standby        #WALの出力内容をレプリケーションに対応
  2. synchronous_commit = local     #同期方式の設定
  3. #synchronous_commitで指定できるレプリケーションの同期方式は下記の通りです。
  4. # 同期:on
  5. # メモリ同期:remote_write
  6. # スレーブ非同期:local
  7. # 完全非同期:off 
  8. max_wal_senders = 2            #スレーブの数 + 1
  9. synchronous_standby_names = 'slave1_test'
  10.  #同期/メモリ同期レプリケーションで同期スレーブとして動作可能なサーバ
  11.  #これを設定しないとスレーブ非同期レプリケーションで動作する。(今回はスレーブ非同期ですが、念の為に設定しておく。)
  12.  #スレーブのrecovery.confに設定するprimary_conninfoのapplication_name=と同一にする

3.pg_hba.confにマスターの設定を追加する


pg_hba.confはPostgreSQLデータフォルダ内にあります。
エディターでファイルを開いて更新します。
  1. host    replication     repl_user        x.x.x.x/xx          password
  2.  #スレーブのrecovery.confに設定するprimary_conninfoのapplication_name=と同一にする

4.マスター側のPostgreSQLを再起動


コマンドは省略

5.マスター側のデータをスレーブで使用するためにバックアップする


pg_basebackupでスレーブサーバ用のデータを作成する
  1. 例)
  2. /opt/local/lib/postgresql92/bin/pg_basebackup -h localhost -p 5432 -D /opt/local/var/db/postgresql92/data_slavedb/ --xlog --progress --verbose 


レプリケーションの設定(スレーブ側)


次にスレーブ側のPostgreSQLの設定をしていきます!

1.マスター側で作成したバックアップをスレーブのデータフォルダへコピーする


データフォルダーごと上書きして更新をする。

2.postgres.confにスレーブの設定を追加する


postgresql.confはPostgreSQLデータフォルダ内にあります。
エディターでファイルを開いて更新します。
  1. hot_standby = on

3.recovery.confにスレーブの設定を追加する


サンプルからコピーしてrecovery.confとファイル名をします。Macの場合は「/opt/local/share/postgresql92/recovery.conf.sample」にありました。
  1. standby_mode = 'on' 
  2. primary_conninfo = 'host=master_hostname port=5432 user=repl_user password=xxx application_name=slave_hostname' #マスターへの接続情報
  3.              #application_nameは同期/メモリ同期の場合にのみ必要
  4.              #マスターのpostgres.confに設定したsynchronous_standby_namesと同一にする

4.スレーブを起動させる


起動しようとしたら【postmaster.opts を読み取ることに失敗しました】とエラーが出た場合は、
postmaster.optsで実行している-dで指定しているデータフォルダを正しい箇所に修正ください。
↓私の環境の場合となります
  1. /opt/local/lib/postgresql92/bin/postgres "-D" "/opt/local/var/db/postgresql92/data_slavedb"
また余談ですが、Macの場合であったのですが、ローカル上で2つのデータフォルダを用意して、それぞれを別ポートで複数立ち上げる場合に、
Macはカーネルで取得できるshared memoryの量がかなり低く設定されているので、shared bufferを確保できずにエラーになることがあります。
下記のコマンドを実行すると起動できるようになります。
  1. sudo sysctl -w kern.sysv.shmmax=1073741824
  2. sudo sysctl -w kern.sysv.shmall=1073741824

5.マスターとスレーブ間で正しく同期がされているかを確認する


  1. ■マスター側で実行
  2. psql -c "select application_name, state, sync_priority, sync_state from pg_stat_replication;"
下記のようになっていれば同期していることになります。


マスター側にデータベースとテーブルとデータ登録をしてスレーブ側に同期されているかを確認します。
  1. psql -p 5432
  2. psql -p 5432 -c "create database sasa_test;"
  3. psql -p 5432 sasa_test
  4. # CREATE TABLE sasa_table (id int primary key,test_text text);
  5. # insert into sasa_table values('1', 'sasa_test');

スレーブ側で反映されているか確認する
  1. psql -p 5433 -l
  2.  ※[データベースリスト]参照
  3. psql -p 5433 sasa_test
  4. # select * from sasa_table;
  5.  ※[データ情報確認]参照
[データベースリスト]


[データ情報確認]


これでPostgreSQLでも同期がされていることが確認できました。今まではPostgreSQLではpg_poolなどを利用してプーリングをさせることが一般的でした。MySQLを使用していた理由としてレプリケーション機能は大きいものでした。これでPostgreSQLでも同様のことができることが確認できましたので、新しいシステムでも使用する頻度もおおくなりそうです。

今回のブログでは「http://codezine.jp/article/detail/7109」の情報を参考に記載させていただきました。この場をお借り致しましてお礼申し上げます。ありがとうございました。