□PostgreSQL9.2のレプリケーションを試してみた
□PostgreSQLのレプリケーションを試してみた
http://lets.postgresql.jp/documents/technical/replication/1
http://www.interdb.jp/techinfo/pg_sr/sr_sync01.html
http://d.hatena.ne.jp/hiroe_orz17/20111113/1321180635
PostgreSQLは9.0から非同期レプリケーション(データ複製とか冗長化とか)
に対応している。9.1からは同期レプリケーションにも対応している。
『レプリケーションだけなら』pgpool-IIとかは要らず、基本的にはマスター
とスレーブ双方でちょこっと設定するだけでOKとなっている。
せっかくなのでコレをCentOSのKVM上に設定して、レプリケーションの実際
をテストしながら試してみる。
マスターサーバーをmaster00として、レプリケーション先サーバーをsub01と
sub02とする。
インストールするパッケージはBASIC SERVERをカスタマイズして、
・WEBサービス
・PHPサポート
・WEBサーバー
・アプリケーション
・EMACS
・サーバー
・電子メールサーバー
・システム管理
・SNMPサポート
・データベース
・PostgreSQLの全て
・開発
・その他の開発
・開発ツール
をとりあえずインストールする。
・master00(192.168.100.200)
virt-install \
–connect qemu:///system \
–name=master00 \
–ram=4096 \
–file=/vps/images/master00.img \
–file-size=10 \
–vcpus=2 \
–os-type=linux \
–os-variant=virtio26 \
–network bridge=br0 \
–accelerate \
–hvm \
–location http://fwnet.or.jp/package/centos/6/os/x86_64/ \
–graphics vnc,port=5900,listen=0.0.0.0,keymap=ja,password=hogehoge \
–extra-args=’hostname=master00′
mv /etc/libvirt/qemu/master00.xml /vps/conf/
ln -s /vps/conf/master00.xml
/etc/libvirt/qemu/autostart/master00.xml
ln -s /vps/conf/master00.xml /etc/libvirt/qemu/master00.xml
・sub01(192.168.100.201)
virt-install \
–connect qemu:///system \
–name=sub01 \
–ram=4096 \
–file=/vps/images/sub01.img \
–file-size=10 \
–vcpus=2 \
–os-type=linux \
–os-variant=virtio26 \
–network bridge=br0 \
–accelerate \
–hvm \
–location http://fwnet.or.jp/package/centos/6/os/x86_64/ \
–graphics vnc,port=5901,listen=0.0.0.0,keymap=ja,password=hogehoge \
–extra-args=’hostname=sub01′
mv /etc/libvirt/qemu/sub01.xml /vps/conf/
ln -s /vps/conf/sub01.xml /etc/libvirt/qemu/autostart/sub01.xml
ln -s /vps/conf/sub01.xml /etc/libvirt/qemu/sub01.xml
・sub02(192.168.100.202)
virt-install \
–connect qemu:///system \
–name=sub02 \
–ram=4096 \
–file=/vps/images/sub02.img \
–file-size=10 \
–vcpus=2 \
–os-type=linux \
–os-variant=virtio26 \
–network bridge=br0 \
–accelerate \
–hvm \
–location http://fwnet.or.jp/package/centos/6/os/x86_64/ \
–graphics vnc,port=5902,listen=0.0.0.0,keymap=ja,password=hogehoge \
–extra-args=’hostname=sub02′
mv /etc/libvirt/qemu/sub02.xml /vps/conf/
ln -s /vps/conf/sub02.xml /etc/libvirt/qemu/autostart/sub02.xml
ln -s /vps/conf/sub02.xml /etc/libvirt/qemu/sub02.xml
…とインストールしてみたら、PostgreSQLのCentOS6.2でのバージョンは
> Name : postgresql
> Arch : x86_64
> Version : 8.4.11
> Release : 1.el6_2
と、古いのでレプリケーションテストが出来ない。
なので、別途PostgreSQLのリポジトリから最新版を取って来る。
http://storagecell.blog.fc2.com/blog-entry-2.html
http://d.hatena.ne.jp/ymko/20120422/p2
マスター、レプリケーション先サーバーそれぞれで、まずはインストール
しちゃった古いパッケージグループを削除
yum -y groupremove PostgreSQL*
で、とりあえずのダウンロード用ディレクトリを作って
mkdir /usr/src/package/
cd /usr/src/package/
PostgreSQL9.2とかを取ってこれるリポジトリを落として来てインストール。
wget http://yum.pgrpms.org/9.2/redhat/rhel-6-x86_64/pgdg-centos92-9.2-5.noarch.rpm
rpm -ivh pgdg-centos92-9.2-5.noarch.rpm
yum search postgresql
として、postgresql92シリーズがリストにある事を確認してから、インストール。
yum -y install postgresql92 postgresql92-devel postgresql92-libs postgresql92-server postgresql92-contrib
で、入ったらデータベースの準備とかしましょう。
service postgresql-9.2 initdb
/etc/init.d/postgresql-9.2 start
chkconfig –level 345 postgresql-9.2 on
あとは、実際のレプリケーションテストに入ること。
■同期レプリケーションの設定
マスターサーバーでレプリケーション用ユーザーの追加
su – postgres
createuser -A -D -P -E –replication sub01
createuser -A -D -P -E –replication sub02
として追加する。
続いてレプリケーション用データベースへのアクセス許可を設定
emacs /var/lib/pgsql/9.2/data/pg_hba.conf
> host replication sub01 192.168.100.0/24 md5
> host replication sub02 192.168.100.0/24 md5
そしたらマスターサーバーのレプリケーション設定をする。
ただし、この段階ではまだレプリケーションはOFFにしておいた方がいいらしい。
emacs /var/lib/pgsql/9.2/data/postgresql.conf
> wal_level = minimal # minimal, archive, or hot_standby
> # (change requires restart)
> archive_mode = off # allows archiving to be done
> # (change requires restart)
> max_wal_senders = 0 # max number of walsender processes
> # (change requires restart)
それと、
> #hot_standby = off # “on” allows queries during recovery
> # (change requires restart)
はあとでonにする。
これらのパラメータをいじったらrestartしろと書いてあるのでする。
/etc/init.d/pdns-server restart
そしたらテスト用のデータを入れてバキュームしてきれいにしておく。
su – postgres
/usr/pgsql-9.2/bin/pgbench -p 5432 -i
vacuumdb –all –analyze
ここまで準備が出来たらマスターサーバーのレプリケーションをONにする。
悩みどころはWAL(ログ先行書き込み)をアーカイブするかどうかだけど、
今回はDBサーバーが別々になるのでNFSも面倒だし、ということでしない
ことにする。実際にはデータベースの用途(信頼性その他)で決定すること。
(ちなみにWALアーカイブをすると手間は増えるがすくいようも増す)
emacs /var/lib/pgsql/9.2/data/postgresql.conf
> wal_level = hot_standby # minimal, archive, or hot_standby
> # (change requires restart)
> max_wal_senders = 3 # max number of walsender processes
> # (change requires restart)
> wal_keep_segments = 8 # in logfile segments, 16MB each; 0 disables
> synchronous_standby_names = ‘sub01, sub02’ # standby servers that provide sync rep
> # comma-separated list of application_name
> # from standby(s); ‘*’ = all
max_wal_sendersはレプリケーション先サーバーを二機としているので2+1で
3としている。
synchronous_standby_namesには、このあとで設定するレプリケーション先
サーバー名(別にHOSTNAMEと同じでなくてもいいけど)を列記する。
そしたらマスターサーバーのPostgreSQLを再起動。
/etc/init.d/pdns-server restart
■マスターサーバーからレプリケーション先サーバーにレプリケーション
まずは一括コピー。
試しに、本来とは違うディレクトリにバックアップコピーしてみる。
su – postgres
mkdir /tmp/sub01
/usr/pgsql-9.2/bin/pg_basebackup \
-h 192.168.100.200 -p 5432 -U sub01 -D /tmp/sub01 \
–xlog=fetch –checkpoint=fast –progress
これで
> 59616/59616 kB (100%), 1/1 tablespace
こんな感じでコピーできたら、本来のデータディレクトリにコピーする。
su – postgres
/usr/pgsql-9.2/bin/pg_basebackup \
-h 192.168.100.200 -p 5432 -U sub01 -D /var/lib/pgsql/9.2/data/ \
–xlog=fetch –checkpoint=fast –progress
続いてレプリケーション先サーバーの設定。
emacs /var/lib/pgsql/9.2/data/postgresql.conf
> hot_standby = on # “on” allows queries during recovery
> # (change requires restart)
emacs /var/lib/pgsql/9.2/data/recovery.conf
> standby_mode = ‘on’
> primary_conninfo = ‘host=192.168.100.200 port=5432 user=sub01 password=areare application_name=sub01’
のようにして、マスターサーバーへの接続設定と、非同期レプリケーション
の時にはなかった「application_name=sub01」という、自身のサーバー名を
設定する。
設定を追加したら、レプリケーション先サーバーsub01のPostgreSQLを
とりあえず手動で起動。
su – postgres
pg_ctl start -D /var/lib/pgsql/9.2/data/
OKそうなら、改めて
/etc/init.d/postgresql-9.2 restart
として、
tail -f /var/lib/pgsql/9.2/data/pg_log/postgresql-*.log
とでもしてみて(実際には再起動した曜日のファイル名:postgresql-Tue.log)
> LOG: スタンバイモードに入ります
> LOG: 0/8000020のREDOを開始します
> LOG: 0/9000000 でリカバリー状態の整合が取れました
> LOG: データベースシステムはリードオンリー接続の受付準備ができました
> LOG: ストリーミングレプリケーションがプライマリに無事接続できました
という感じになる。
マスターサーバー側のログも見てみると、
> ステートメント: application_name,state,sync_priority,sync_state FROM pg_stat_replication;
> LOG: スタンバイの “sub01” には優先度 1 で同期スタンバイが設定されています
と言うようにsub01が繋がったというメッセージが出る。
この時に
psql -x -p 5432 -c “SELECT application_name,state,sync_priority,sync_state FROM pg_stat_replication;”
とすると、
> -[ RECORD 1 ]—-+———-
> application_name | sub01
> state | streaming
> sync_priority | 1
> sync_state | sync
というように確認できる。
さらにsub02もPostgreSQLを再起動すると、
> -[ RECORD 1 ]—-+———-
> application_name | sub01
> state | streaming
> sync_priority | 1
> sync_state | sync
> -[ RECORD 2 ]—-+———-
> application_name | sub02
> state | streaming
> sync_priority | 2
> sync_state | potential
のように増える。
ログにはsub02のメッセージが出てこないのが気になると思うが、
http://www.interdb.jp/techinfo/pg_sr/sr_sync01.html
「PostgreSQL ver9.1の同期レプリケーションはスレーブ1台のみ有効なので
slave2はslave1が停止するまで”非同期レプリケーション”で稼働する」
ということらしい。
■レプリケーションの確認
マスターサーバーで、以下の二行をコピペする。
/usr/pgsql-9.2/bin/pgbench -p 5432 -T 180
psql -x -p 5432 -c “SELECT * FROM pg_stat_replication”
すると、
> -[ RECORD 1 ]—-+——————————
> pid | 23391
> usesysid | 16470
> usename | sub01
> application_name | walreceiver
> client_addr | 192.168.100.201
> client_hostname |
> client_port | 59310
> backend_start | 2012-06-19 13:08:56.288866+09
> state | streaming
> sent_location | 0/C159CB0
> write_location | 0/C159CB0
> flush_location | 0/C159CB0
> replay_location | 0/C159AA0
> sync_priority | 0
> sync_state | async
となるが、この時「sent_location」と「replay_location」の差が同期の差。
少ししてからまた
psql -x -p 5432 -c “SELECT * FROM pg_stat_replication”
とすると、
> -[ RECORD 1 ]—-+——————————
> pid | 23391
> usesysid | 16470
> usename | sub01
> application_name | walreceiver
> client_addr | 192.168.100.201
> client_hostname |
> client_port | 59310
> backend_start | 2012-06-19 13:08:56.288866+09
> state | streaming
> sent_location | 0/C15E6F0
> write_location | 0/C15E6F0
> flush_location | 0/C15E6F0
> replay_location | 0/C15E6F0
> sync_priority | 0
> sync_state | async
というように、差がなくなって同期も取れたことが判る。
またレプリケーション先サーバーで
psql -p 5432 -c “SELECT pg_last_xact_replay_timestamp()”
とすると、いつまでのデータをマスターサーバーからレプリケーションしたか
という日時を見ることが出来る。
> pg_last_xact_replay_timestamp
> ——————————-
> 2012-06-19 13:16:23.2158+09
レプリケーション処理が発生しないと、コレは空っぽのまま。
■トラブル発生時の対応方法
参考URLにも書いてあるが、PostgreSQLはそれ自体がトラブって落ちたとして
も、何か便利に自動的に切り替わってサービスが継続できると言うわけでは
ない。
Pacemakerやpgpool-IIの管理機能などを組み合わせることで、上位アプリが
(比較的)意識しなくてもデータベースが切り替わるように仕組みを作らないと
いけない。
これはぶっちゃけ、システム構築をする自分たちでその経験を活かしつつ、
自分たちでサービスを継続する仕組みそのものを作ったほうがいいと未だに
思う。上記のようなツールを使っても、トラブルがそれらの想定を超えた場合
には、何も出来なくなるようなことは避けたほうがよい。
どうせトラぶった時のデータの整合性を確認しなければならないのだから、
いかに迅速にサービスを復旧できるかだろう。
レプリケーションのメリットは、このいわばほぼリアルタイムバックアップ
ができるということと、参照に限った負荷分散と言うことになるんだろうか
なー。
とにかく一度はやってみると、レプリケーションと言うのは何処まで、どの
ようにやってくれるのか判るので、何処から自分たちでフォローしなければ
いけないかも見えてくるんじゃないかと思う。