トリアエズぶろぐ
フリーランスでやってる77世代のWEBプログラマが福岡からのんびりとお送りいたします。
スポンサーサイト


一定期間更新がないため広告を表示しています

<< 【つなビィ】のAndroidアプリをリリースしました。 | main | Mac OS X Server 10.8 でntpサーバを設定する >>
CentOSでPostgreSQL9.2の同期レプリケーションを試してみたよ


ずっと気になってたPostgreSQL9.2からできるようになった同期レプリケーション。
やっと試してみました。

PostgreSQL9.2では、
・同期
・メモリ同期
・スレーブ非同期
・完全非同期
の4種類のレプリケーションがありますが、今回はメモリ同期を試してみました。

PostgreSQL9.2のインストール

まずはPostgreSQLのリポジトリ追加

http://yum.postgresql.org/9.2/redhat/rhel-5-x86_64/
で【pgdg-centos92-9.X.X】の最新版をインストール

# rpm -ivh http://yum.postgresql.org/9.2/redhat/rhel-5-x86_64/pgdg-centos92-9.2-6.noarch.rpm

PostgreSQL9.2をインストール

# yum install --enablerepo=pgdg92 postgresql92*

起動後にテストデータを入れてみる

# su - postgres
$ /usr/pgsql-9.2/bin/pg_ctl restart -D /var/lib/pgsql/9.2/data -l ~/9.2/master.log $ createdb --encoding=UTF8 --template=template1 testdb $ /usr/pgsql-9.2/bin/pgbench -i testdb $ /usr/pgsql-9.2/bin/pgbench testdb -c 3 -t 500 -p 5432

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

【postgresql.conf】
wal_level = hot_standby           # レプリケーション対応
synchronous_commit = remote_write # メモリ同期レプリケーション

max_wal_senders = 4               # とりあえずスレーブ3台まで
synchronous_standby_names = '*'   # 今回は全て(メモリ)同期レプリケーションするので * にした
wal_keep_segments = 16
replicationの部分をイキにする
METHODが peer/ident の場合、UNIXユーザ認証を使う。
今回はテストなのでlocalからは全て trust に変更。
【pg_hba.conf】
local   all             all                                     trust
host    all             all             127.0.0.1/32            trust
local   replication     postgres                                trust
host    replication     postgres        127.0.0.1/32            trust

再起動

$ /usr/pgsql-9.2/bin/pg_ctl restart -D /var/lib/pgsql/9.2/data -l ~/9.2/master.log

pg_basebackupでスレーブサーバ作成

pg_basebackupは稼働中のDBからスレーブ用のバックアップデータを取れるすぐれもの。
今回は data_slave ディレクトリにバックアップを取ります。

$ /usr/pgsql-9.2/bin/pg_basebackup -h localhost -p 5432 -D ~/9.2/data_slave --xlog --progress --verbose

スレーブサーバ用に設定ファイルを編集

【~/9.2/data_slave/postgresql.conf】
port = 5433                   # 同サーバで複数のDBを動かすために変更
hot_standby = on
log_line_prefix = '[slave1]'  # 必須じゃないけど一応スレーブの名前をつける

recovery.confをサンプルからコピー

$ cp /usr/pgsql-9.2/share/recovery.conf.sample ~/9.2/data_slave/recovery.conf
【~/9.2/data_slave/recovery.conf】
standby_mode = on
primary_conninfo = 'host=localhost port=5432 application_name=slave1'

起動しようとしたら【postmaster.opts を読み取ることに失敗しました】って怒られた…

$ cp ~/9.2/data/postmaster.opts ~/9.2/data_slave/
$ vi ~/9.2/data_slave/postmaster.opts
/usr/pgsql-9.2/bin/postgres "-D" "/var/lib/pgsql/9.2/data_slave"

スレーブ起動

$ /usr/pgsql-9.2/bin/pg_ctl restart -D /var/lib/pgsql/9.2/data_slave -l ~/9.2/slave1.log

と、この時点で既にデータが同期されている!スゴー。

念のため確認、スレーブにはinsertできないはず。

$ psql -p 5433 -c "INSERT INTO pgbench_history VALUES (1,1,1,1,now())" testdb
ERROR:  リードオンリーのトランザクションでは INSERT を実行できません

おっけー。

しかしここでちょっとした罠が。

PostgreSQL 9.2ではマスター1台スレーブ1台のレプリケーション構成で同期/メモリ同期を採用した場合、
スレーブへのWAL書き込みをマスターがタイムアウトせずに待つ仕様になっています。
このためスレーブの障害の発生がマスターがスレーブへのWAL書き込み待ちと同じタイミングの場合、
マスターの処理も停止し、クライアントへ処理結果が返りません。つまりスレーブが単一障害点です
http://codezine.jp/article/detail/7109?p=2

2台以上のスレーブがないと障害時に完全停止してしまう…ということで同じ手順でslave2も作成しましょう。

レプリケーション状況を確認

slave2を起動した所でレプリケーション状況を確認

$ psql -p 5432 -c "SELECT application_name,state,sync_priority,sync_state FROM pg_stat_replication"
application_name |   state   | sync_priority | sync_state
------------------+-----------+---------------+------------
slave1           | streaming |             1 | sync
slave2           | streaming |             1 | potential

sync … 同期で転送されている
potential … 現在は非同期転送だが、より上位のノードとの接続が無くなった場合に同期に格上げされる可能性がある
ステータスの説明はこちらがわかりやすい。
http://thinkit.co.jp/story/2011/10/27/2319

データの整合性を確認する

こんなかんじで。

/usr/pgsql-9.2/bin/pgbench testdb -c 3 -t 500 -p 5432;
psql -p 5432 -c "SELECT aid, delta, mtime FROM pgbench_history LIMIT 1" testdb;
psql -p 5433 -c "SELECT aid, delta, mtime FROM pgbench_history LIMIT 1" testdb;
psql -p 5434 -c "SELECT aid, delta, mtime FROM pgbench_history LIMIT 1" testdb;

値が同じ、ちゃんと同期してる!

リカバリを試してみる!

ちょっと意地悪して、こんなスクリプトで常にinsert/updateしている状況でリカバリを試してみる

$ vi ~/update_db_continuously.sh
#!/bin/sh

while true
do
/usr/pgsql-9.2/bin/pgbench testdb -c 3 -t 500 -p 5432
sleep 2
done

insert/update中にslave2を停止 ⇒ しばらくして意地悪スクリプトを停止 ⇒ slave2を起動 ⇒ 整合性確認 ⇒ バッチリ!

ちなみに意地悪スクリプトを動かしている最中にslave1を停止すると

/usr/pgsql-9.2/bin/pg_ctl stop -D /var/lib/pgsql/9.2/data_slave;
psql -p 5432 -c "SELECT application_name,state,sync_priority,sync_state FROM pg_stat_replication";

application_name |   state   | sync_priority | sync_state
------------------+-----------+---------------+------------
slave2           | streaming |             1 | sync
(1 行)

slave2がsync(同期レプリケーション)になる

しばらくしてslave1を起動すると

/usr/pgsql-9.2/bin/pg_ctl restart -D /var/lib/pgsql/9.2/data_slave -l ~/9.2/slave1.log;
application_name |   state   | sync_priority | sync_state
------------------+-----------+---------------+------------
slave1           | streaming |             1 | sync
slave2           | streaming |             1 | potential
(2 行)

ちゃんと戻ってる!
もちろん、データの整合性もバッチリ!ゴイスー

 

 

以下のサイトを参考にさせて頂きました。ありがとうございます。

PostgreSQL 9.2の同期レプリケーションを利用する際の勘所
http://codezine.jp/article/detail/7109
ごろねこ日記
http://d.hatena.ne.jp/hiroe_orz17/searchdiary?word=PostgreSQL
PostgreSQL9.0レプリケーション・ハンズオン
http://www.ospn.jp/osc2011-oita/pdf/osc2011oita-jpug_2.pdf

スポンサーサイト


COMMENT









Trackback URL
http://akihiro.jugem.jp/trackback/298
TRACKBACK