Hatena::Grouppostgresql

PostgreSQL 雑記 このページをアンテナに追加 RSSフィード

2010-07-14レプリケーションでのノード構成 このエントリーを含むブックマーク このエントリーのブックマークコメント

PostgreSQL 9.0 でホット・スタンバイ + ストリーミング・レプリケーションの構成を取る場合、大きく分けて3種類のノード構成があります。それぞれの構成の特徴や注意が必要な点を調べてみます。

  1. アーカイブログを取得し、複数のノードで共有する
  2. アーカイブログを取得し、複数のノードで共有しない
  3. アーカイブログを取得しない

どの構成でも設定パラメータ wal_level は hot_standby にしておきます。

1. アーカイブログを取得し、複数のノードで共有する

この構成では、レプリケーション時の WAL の転送には、アーカイブログとストリーミングの両方を利用できます。設定がシンプルなので、たぶん一番使いやすい構成です。archive_command には全てのノードで同じ共有ファイルサーバのパスを指定すれば良いですし、フェイルオーバーでマスターノードが移動しても運用を変える必要がありません。

  • archive_mode = on
  • archive_command = 'cp %p /共有ファイルサーバのパス/%f'
  • wal_keep_segments = 0

ひとつ注意が必要なのは、複数のノードが同時にマスタになること (いわゆる スプリット・ブレイン) が無いよう制御する必要があることです。アーカイブログを共有サーバに保存するため、上書きが起こるとバックアップのデータが壊れてしまいます。特に、サーバがクラッシュした際に自動的に各プロセスの再起動がかかるため、単にスタンバイの1つをマスターにするだけでなく、マスターを完全に殺し切る必要があります*1。監視ミドルウェアを使うならば、pgpool の次期版か、Heartbeat や Pacemaker のリソースエージェント (RA) を自作することになると思われます。

また、アーカイブログの置き場になるファイルサーバがある意味 Single Point of Failure になるので、すぐにデータベースが止まることは無いものの、注意が必要です。

2. アーカイブログを取得し、複数のノードで共有しない

アーカイブログを共有しないため、データの上書きや SPoF の心配はありません。とはいえ、複数のノードが同時にマスタになった場合は、確かに各ノードのデータは壊れませんが、サービス全体としては一貫性の無い状態 (例えば、予約の "ダブル・ブッキング") に陥る恐れもあり、メリットとは考えないほうが良いかもしれません。

  • archive_mode = on
  • archive_command = 'cp %p /ノードごとに異なるパス/%f'
  • wal_keep_segments = 0

ただし、ノード間をマスター役が移動するとアーカイブログが複数の場所に散らばるので、各場所を調べるような restore_command が必要になります。運用には手間がかかります。とはいえ、ロケーションの異なるノード間でレプリケーションを行うディザスタ・リカバリのような場合には、アーカイブログ用のファイルサーバを共有しづらいため、この構成が必要になるかもしれません。9.0 現在、スタンバイの最中にはアーカイブログを作成しない (マスターに昇格するまで archive_command が働かない) ことに注意します。

3. アーカイブログを取得しない

レプリケーションはするが、オンライン・バックアップは要らないという用途向きです……が、現実にそういう状況があるのかどうか良くわかりません。アーカイブ処理が要らないので、ディスクの節約にはなります。

  • archive_mode = off
  • wal_keep_segments = ディスク容量の許す限り、たくさん

アーカイブログが利用できないため、ベース・バックアップ以降の全ての変更はストリーミング経由で転送することになります。あまりに大量の更新があると古いWALがリサイクルされてしまい、変更が転送できなくなります。それを防ぐために wal_keep_segments でしばらく古いWALを残すことになります。アーカイブ不要で節約した分、アクティブログが増えるので、あまり得になっていないかもしれません。


というわけで、同一ロケーション内でのレプリケーション構成が目的ならば、1.の構成が適していると思われます。この構成について、もうちょっと探ってみます。

*1:9.1では restart_after_crash オプションが追加される見込み。

interdbinterdb2010/07/15 11:322.は「サービス全体として一貫性を保てない可能性」とありますが、具体的には"マスタでcommit直後、スレーブにログを送る前にクラッシュ。スレーブはログを受け取ってないので未更新。アプリ側では更新済み"という状況でしょうか。

pgsqlpgsql2010/07/20 09:22いえ、スプリット・ブレインの文脈です。この状況でも一応データの破壊は免れますが、複数のマスタが更新処理を受け付けてしまうため、「ダブル・ブッキング」的な問題が生じる可能性があります。

Tatsuo IshiiTatsuo Ishii2010/09/24 09:47ストリーミングレプリケーションでは、アーカイブログはレプリケーションには使われないと思うのですが、いかがでしょう。つまり、スタンバイのレプリケーションが追いつかなくなって、レプリケーションが切れてしまうのを防ぐのには、アーカイブロギングの設定は役に立たないと思います。

pgsqlpgsql2010/09/24 09:55この記述は、むしろ「最初に追い付くまで」のことを想定していました。時間が経ち過ぎると古いWALは消えてしまいますが、いっそアーカイブを使う前提で構成して、wal_keep_segmentsに気を使わずに済ませるのが楽かと考えました。

追いつかなくなった後、アーカイブ内ならWALが残っている時の動作はちゃんと考えてませんでした。再びアーカイブ→直接転送の順で追いついてもらえると、エラーになることは避けられるので嬉しい気がします。もし現状そうなっていなければ、そうなるよう改善したいところです。

Tatsuo IshiiTatsuo Ishii2010/09/24 19:04ストリーミングレプリケーションの作者に直接確認したところ:-)、追いつかなくなる→アーカイブからリカバリを試みる→うまくいったら再び直接転送モード... のように動いてくれるそうです。素晴らしい!