WebアプリのHAセットアップを作成するために、PGプールを使用して2つのサーバーをセットアップしました。
PGPoolとpostgresは、サーバー1からサーバー2へのストリーミングレプリケーションを使用して、両方のサーバーで実行されます。各マシンのWebアプリはPgPoolに接続し、PgPoolは要求を現在のマスターに送信します。データベース接続が中断された場合に自動的にフェイルオーバーするように設定されています。これにより、カスタムフェイルオーバースクリプトが実行され、サーバー1がスレーブに降格され、サーバー2がマスターに昇格されます。
今朝起こったことは、2分間ネットワークがダウンしたことです。つまり、どちらのPGPoolインスタンスも相互に通信できなかったため、各PGPoolは他のマシンがダウンしていると考えました。
サーバー1-マスターとして続行し、サーバー2を切断します
サーバー2-フェイルオーバーを開始し、サーバー1を切断して、サーバー自体をマスターにします
ネットワークがダウンしていたため、フェイルオーバーコマンドはサーバー1に到達してスレーブにすることができず、その逆も同様でした。したがって、2分後にネットワークが復旧したとき、私が持っていたのは2台のサーバーで、どちらもマスターだと思っていました。
PgPoolには自動フェールバックコマンドがないようです。これは、ネットワークが再接続したときにサーバー1を強制的にマスターにするために使用できます。これは、私が考えることができる唯一の実際のソリューションです。
私の質問は、この状況にどのように対処するのかということです。これは、このセットアップの正しいアーキテクチャでもありますか?確かにこれは一般的なシナリオであり、この種の問題をどのように修正できるかについて頭を悩ませることはできません。
編集:linux-haの仮想IPでpgpoolを実行することをお勧めしますか?それcould問題を解決し、私はすでにパブリックIPに対してそれを稼働させています-そうすれば、どちらのマシンからも1つのpgpoolインスタンスにのみアクセスできます。
まず、pgpool2にはフェイルバックコマンドがあると思いますが、その場合はあまり役に立ちません。問題は、両方のマシンが自分をマスターだと思った場合に混乱が生じることです。さらに、ここでは単純なケースがありました。ネットワークがダウンしたということです。ネットワークがパーティション化されている場合はどうなりますか?つまり、両方のマシンは接続されていますが、どういうわけか相互の接続が失われています。その場合、両方のマシンがマスターになり、異なるクライアントにサービスを提供し、データベースがフォークされます。まれなケースですが、結果として生じる混乱のリスクを冒す準備ができている可能性が非常に低いと確信していますか?
別の方法は次のとおりです。
+- master db
|
------ pgpool ------+
|
+- hot standby
ただし、その場合は、単一障害点pgpoolがあり、これはおそらく望ましくありません。私はこの問題に対処する2つの方法しか知りません。最も簡単なのは、スタンバイをマスターに手動で昇格させることだけです。これは、アーキテクチャに適用できます。アプリケーションは、人間が介入するまで読み取り専用モードにする必要があります。
2番目の方法は、クォーラムを持つことです。動作する可能性のあるアーキテクチャの1つは、次のとおりです。
+--- pgpool standing by -+ +- master db
| | |
failover ip -+--- active pgpool -+----+- hot standby 1
| | |
+--- pgpool standing by -+ +- hot standby 2
|
+- hot standby 3
(as many standby servers as
you want, so that you have
read-only load balancing)
3つのpgpoolは、それぞれが独自のIPアドレスを持つ3つの異なるマシンで実行されていますが、アクティブなマシンによってのみ取得される追加のフェイルオーバーIPアドレスも提供し、クライアントによって使用されます。アクティブなpgpoolに障害が発生した場合、スタンバイpgpoolがそれを引き継ぎます。これはheartbeat
で実現できます。
ホットスタンバイをマスターに昇格させるには、pgpoolのクォーラム(つまり、3つのうち少なくとも2つ)がそのように決定する必要があります。そして、彼らは決定後、例えば10秒の遅延の後にのみ決定を実行します。さらに、アクティブなpgpoolは、少なくとも別のpgpoolからの確認を取得せずに、既存のマスターデータベースを10秒以上使用し続けることはできません(これは、2つのスタンバイpgpoolがアクティブなpgpoolへの接続を失った場合を防ぐためです。同時にマスターは、ホットスタンバイをマスターに昇格させますが、アクティブなpgpoolは引き続き古いマスターを使用します)。
実際には、3番目のpgpoolはフェイルオーバーIPに参加する必要はなく、クォーラムを支援するためにそこにいるだけです。さらに、pgpoolにこれを行うのに十分な機能があるかどうかはわかりません。たぶん、別のデーモンが必要です。より一般的なアーキテクチャは次のとおりです。
+--- active pgpool -+ +- master db
| | |
failover ip -+ -+----------+- hot standby 1
| | |
+--- pgpool standing by -+ +---+- hot standby 2
| |
| +- hot standby 3
monitoring daemon 1 ---+ |
| |
monitoring daemon 2 ---+------+
|
monitoring daemon 3 ---+
この場合、pgpoolによって実行されるロードバランシングは、スタンバイの監視およびマスターへの昇格から分離されます。 pgpool、データベースサーバー、および監視デーモンを同じマシンに配置できますが、2つのpgpoolは2つの異なるマシンに配置し、3つの監視デーモンは3つの異なるマシンに配置する必要があることに注意してください。必要なすべての機能を備えた既製の監視デーモンが存在するかどうかはわかりません。
詳細は変更可能ですが、クォーラムを使用せずにマスターへの自動スタンバイ昇格を行うと、トラブルが発生していると思います。
これは、このセットアップの正しいアーキテクチャでもありますか?確かにこれは一般的なシナリオであり、この種の問題をどのように修正できるかについて頭を悩ませることはできません。
免責事項:私はpgpoolを使用していませんが、それが何をするのかは知っています。
クラスタリングソフトウェアでは、クラスターがノードの半分未満のステータスを認識している場合に、同時実行ルールに違反する可能性のある自動化された操作(たとえば、何かが1か所でのみオンラインである必要があります)を実行したくないのが一般的です。これにより、経験したようなスプリットブレイン状態を防ぐことができます。 2ノードのクラスターでは、これは、2つのノード間のネットワーク相互接続が失われた場合に、自動フェイルオーバーが発生しないことを意味します。人間は、オフラインになっている「他の」ノードに応じて、フェイルオーバーが正しいアクションであることを確認するか、複製されていないトランザクションが失われる可能性があることを受け入れて、フェイルオーバーを決定する必要があります。これがpgpoolで構成できるものかどうかはわかりません。
サーバーが同じLANにある場合(相互にアクセスするためのネットワーク遅延が少ない場合)、レプリケーションマルチマスターモードでpgpoolを実行することを検討できます。 2つのデータベースを同時に更新する必要があるため、少しオーバーヘッドが発生します。
1つのシステム障害が発生した場合、pgpoolはアクティブノードを介してアクセスを提供し続けることができます。システムの回復後、pgpoolでオンライン回復を実行して、他のノードを起動できます。