2015年09月

ErogameScapeのPostgreSQLの論理構成

ErogameScapeのPostgreSQLは以下のような構成でした。
--- pgpool ---- サーバー1
    (レプリケーションモード)
      |
      |
      --------- サーバー2
                   |
                   | ↓1日1回、pg_dumpしたデータを送りつけ
                   |
                サーバー3(さくらインターネット)
サーバー1と2に同時に障害が発生した場合…というか、サーバー1と2の設置しているロケーションが駄目になった場合、最大で1日データが巻き戻りました。

そこで、先日以下のような構成に変更しました。

--- pgpool ---- サーバー1
    (レプリケーションモード)
      |
      |
      --------- サーバー2
                   |
                   | ↓非同期レプリケーション
                   |
                サーバー3(さくらインターネット)
私自身が無事であれば、DNSの設定を変更し、サーバー3をMasterに昇格させることでサービスの復旧が可能になりました。

PostgreSQLを趣味で使い始めてから15年がたちました。
レプリケーションの技術についてはいまいちだなあ…と思っていましたが、今ならスケールアウトがすごく手軽に出来るなあ…と思いました。

ErogsmScapeはスケールアウトは必要なく、確か5年前からスケールアップすらも必要なくなりましたので、その恩恵にあずかることはないのですが、Verがあがるたびに性能も改善されているので、スケールアップも必要ないのかな…と思っています。
※もちろん訪れる方が横ばいであるというのもあります…

PostgreSQLの開発者の方々に感謝申し上げます。

PostgreSQL9.3のストリーミングレプリケーションについて

PostgreSQLのレプリケーション機能は9.0で実装されて以降、Verがあがるたびに劇的に機能が追加されていきます。

PostgreSQLのレプリケーション機能の文書を参照するとき、その文書がいくつのVerの機能を元に書かれているかに気をつけて読む必要があります。

「PostgreSQL9.3でレプリケーション機能を試した」という文書でも、実は9.3で追加された機能を活かしきっていなくて、9.2までの機能で書かれていることがある…ことに気をつけなければいけません。

このような自体が発生するのは、新しいVerの機能を使ってレプリケーションを機能を試している文書がとても少ないから…だと思います。
同じVerのPostgreSQLでレプリケーション機能を試している文書なのに、手順が違っていて「おやっ?」と思うことがあります。

また、PostgreSQLの公式の文書はとても充実しているのですが、文章の方が多くて、いまいち具体的にどう設定して、どうコマンドをたたけばいいかが分かりにくいのも問題なのかと思います。

PostgreSQL9.3のストリーミングレプリケーションについて9.3で追加された
ストリーミングレプリケーションのスタンバイのタイムラインスイッチへの追従が可能になりました。(Heikki Linnakangas)
の機能を使ったレプリケーション環境の構築および復旧について実践ベースで記載されたWeb上で閲覧できる日本語の文書は2015年9月26日時点で以下の文書のみじゃないかなと思います。

SRA OSS,Inc.のPostgreSQL 9.3 beta1 検証レポート

4.7. ストリーミングレプリケーションの拡張

また、ストリーミングレプリケーションのスタンバイのタイムラインスイッチへの追従が可能になったことで、何がうれしいのか?を図を用いて解説している日本語の文書は、おそらく以下の文書だけかなと思います。

PostgreSQL9.3 新機能を検証してみた Vol.2

PostgreSQLの可用性を支えるストリーミング・レプリケーション


PostgreSQL9.2まではサーバー1(Master)とサーバー2(Slave)構成において、サーバー1を切り離した後(障害が発生した後)、サーバー1をサーバー2(Master)のSlaveとして復旧させるには、
(1)pg_basebackupからやらなおす
(2)recovery.confに以下の2つを追加してpg_ctl startする
recovery_target_timeline='latest'
restore_commandでMasterから.historyを転送するコマンドを追加する
が必要でした。

※2015年9月26日現在、上記で紹介した文書以外の文書においてはその文書で使用しているPostgreSQLのVerを問わず、(1)の方法で復旧させています。

※(2)の方法が書いてあるのは、ストリーミング・レプリケーションの構築 Let's Postgresだけだと思います。

※障害の度合いによってはベースアップの取得からはじめないといけないケースもあると思います。

PostgreSQL9.3のレプリケーション機能の目玉は「ストリーミングレプリケーションのスタンバイのタイムラインスイッチへの追従が可能になった」ことです。
この機能は上記の「restore_commandでMasterから.historyを転送する」を自動で実施してくれるようになったこと…と解釈しています。
どんな機能か?の公式ドキュメントは「ストリーミングレプリケーションプロトコル」の「TIMELINE_HISTORY tli」です。TIMELINE_HISTORYが9.3で追加されました。

※pgpoolのオンラインリカバリ機能は結構複雑だと思っていて、restore_commandの指定を間違うことが多かったのでrestore_commandを指定することにためらいがあるのですが、こうして自動でやってくれる機能が追加されるのはうれしいです。


それでは実際に試した結果を以下に記載します。
※いろいろさっぴいているので、そのまま以下の手順をなぞっても動きません。

192.168.0.20にPostgreSQLをポート5432で立ち上げています。
ポート5432で動かしているPostgreSQLにはレプリケーションのための設定がされているとします。
ポート5433で動かすためのベースバックアップを取得します。
$ pg_basebackup -h 192.168.0.20 -p 5432 -U replication_user -D /home/postgres/data5433 --xlog --progress --verbose --write-recovery-conf

※pg_basebackupに--write-recovery-confというオプションを追加すると、レプリケーションをするためのrecovery.confを作成してくれます。このオプションは9.3で追加されました。しかし、文書によっては9.3で機能検証しているけどwrite-recovery-confを指定しないで、recovery.confをrecovery.sampleをベースに書いています。注意が必要です。

ポート5433で動かすために設定を変更します。
$ emacs /home/postgres/data5433/postgresql.conf
port=5433

ポート5433で起動します。
$ /usr/pgsql-9.3/bin/pg_ctl start -D /home/postgres/data5433/

レプリケーションがされているかを確認します。
$ /usr/pgsql-9.3/bin/psql -p 5432
psql (9.3.9)
"help" でヘルプを表示します.

postgres=# SELECT * FROM pg_stat_replication;
  pid  | usesysid |     usename      | application_name | client_addr  | client_hostname | client_port |         backend_sta
rt         |   state   | sent_location | write_location | flush_location | replay_location | sync_priority | sync_state
-------+----------+------------------+------------------+--------------+-----------------+-------------+--------------------
-----------+-----------+---------------+----------------+----------------+-----------------+---------------+------------
 11829 | 80599313 | replication_user | walreceiver      | 192.168.0.20 |                 |       44524 | 2015-09-23 21:10:07
.192273+09 | streaming | 1E0/990000C8  | 1E0/990000C8   | 1E0/990000C8   | 1E0/990000C8    |             0 | async
(1 行)
※ErogameScapeではバックアップのためにレプリケーション機能を使っているので非同期モードです。

ポート5432のPostgreSQLを停止します。
$ /usr/pgsql-9.3/bin/pg_ctl stop -D /home/postgres/data5432/
サーバ停止処理の完了を待っています....完了
サーバは停止しました

ポート5433のPostgreSQLをMasterに昇進します。
-bash-4.1$ /usr/pgsql-9.3/bin/pg_ctl promote -D /home/postgres/data5433/
サーバを昇進中です。

ポート5432のPostgreSQLをポート5433のPostgreSQLのSlaveとして復旧させるためのrecovery.confのひな形をポート5432のPostgreSQLのDATAディレクトリに配置します。
$ cp /home/postgres/data5433/recovery.done /home/postgres/data5432/recovery.conf

recovery.confのポート番号を書き換えます。
また、最新のタイムラインに追随するよう、recovery_target_timeline='latest'を書き加えます。
$ emacs /home/postgres/data5432/recovery.conf
standby_mode = 'on'
primary_conninfo = 'user=replication_user password=パスワード host=192.168.0.20 port=5433 sslmode=prefer sslcompression=1 krbsrvname=postgres'
recovery_target_timeline='latest'


ポート5432のPostgreSQLを起動します。
$ /usr/pgsql-9.3/bin/pg_ctl start -D /home/postgres/data5432/

ログ(マスター側 : ポート5433)
< 2015-09-23 21:15:14.883 JST > user= p=11824 LOG:  received promote request
< 2015-09-23 21:15:14.883 JST > user= p=11824 LOG:  redo done at 1E0/99000168
< 2015-09-23 21:15:14.991 JST > user= p=11824 LOG:  selected new timeline ID: 80
< 2015-09-23 21:15:15.276 JST > user= p=11824 LOG:  archive recovery complete
< 2015-09-23 21:15:15.462 JST > user= p=11824 LOG:  MultiXact member wraparound protections are now enabled
< 2015-09-23 21:15:15.463 JST > user= p=11822 LOG:  database system is ready to accept connections

起動ログ(スレーブ側
: ポート5432)
< 2015-09-23 21:18:51.797 JST > user= p=11897 LOG:  database system was shut down at 2015-09-23 21:13:42 JST
< 2015-09-23 21:18:51.797 JST > user= p=11897 LOG:  entering standby mode
< 2015-09-23 21:18:51.895 JST > user= p=11897 LOG:  consistent recovery state reached at 1E0/990001D0
< 2015-09-23 21:18:51.895 JST > user= p=11897 LOG:  record with zero length at 1E0/990001D0
< 2015-09-23 21:18:51.895 JST > user= p=11895 LOG:  database system is ready to accept read only connections
< 2015-09-23 21:18:51.899 JST > user= p=11901 LOG:  fetching timeline history file for timeline 80 from primary server
< 2015-09-23 21:18:51.965 JST > user= p=11901 LOG:  started streaming WAL from primary at 1E0/99000000 on timeline 79
< 2015-09-23 21:18:51.966 JST > user= p=11901 LOG:  replication terminated by primary server
< 2015-09-23 21:18:51.966 JST > user= p=11901 DETAIL:  End of WAL reached on timeline 79 at 1E0/990001D0.
< 2015-09-23 21:18:51.966 JST > user= p=11897 LOG:  new target timeline is 80
< 2015-09-23 21:18:51.966 JST > user= p=11901 LOG:  restarted WAL streaming at 1E0/99000000 on timeline 80
< 2015-09-23 21:18:52.237 JST > user= p=11897 LOG:  redo starts at 1E0/990001D0


ポート5432のPostgreSQLでレプリケーションの状態を確認します。
$ /usr/pgsql-9.3/bin/psql -p 5433 -U ap2
psql (9.3.9)
"help" でヘルプを表示します.

ap2=# SELECT * FROM pg_stat_replication;
  pid  | usesysid |     usename      | application_name | client_addr  | client_hostname | client_port |         backend_sta
rt         |   state   | sent_location | write_location | flush_location | replay_location | sync_priority | sync_state
-------+----------+------------------+------------------+--------------+-----------------+-------------+--------------------
-----------+-----------+---------------+----------------+----------------+-----------------+---------------+------------
 11902 | 80599313 | replication_user | walreceiver      | 192.168.0.20 |                 |       47392 | 2015-09-23 21:18:51
.898254+09 | streaming | 1E0/99003028  | 1E0/99003028   | 1E0/99003028   | 1E0/99003028    |             0 | async
(1 行)



pg_basebackup: サーバからトランザクションログの終了位置を入手できませんでしたについて

以下のメッセージが出ても、再度実行すると問題なくcompletedします。

pg_basebackup: サーバからトランザクションログの終了位置を入手できませんでした: ERROR:  requested WAL segment 0000004F000001E000000055 has already been removed

3回目でようやくcompletedになることもあります。
設定に問題があれば再度実行しても失敗すると思うのですが、何も変更せず、ただ再度実行するだけで成功するで、おそらく設定に問題は無い…と思います。
ローカルネットワークでも失敗することがあるのでデータの転送に時間がかかるから失敗する…というわけでもないと思います。

PostgreSQLのストリーミング・レプリケーションのpg_hba.confについて

PostgreSQLのストリーミング・レプリケーションでスタンバイDB用のデータベースを作成する場合、pg_basebackupコマンドを使用します。

例えば以下のようなコマンドになります。
$ pg_basebackup -h 192.168.0.13 -p 5432 -D /var/lib/pgsql/9.3/data --xlog --progress --verbose

この時
pg_basebackup: サーバに接続できませんでした: FATAL:  no pg_hba.conf entry for replication connection from host "192.168.0.20", user "postgres", SSL off
と出力された場合、pg_hba.confの設定が足りていません。

例えば
host    replication postgres     192.168.0.20/32      trust
のように、replication用の設定を追加する必要があります。

ErogameScapeの環境のpg_hda.confの設定には
host    all         all          192.168.0.0/24      trust
と書いてあるので、replication用の設定はいらないと思っていたのですが、pg_hda.confには

# Allow replication connections from localhost, by a user with the
# replication privilege.

と書いてあるので、allの中にはreplicationは含まれておらず、replicatioを単体で設定する必要があるようです。
記事検索