Slony-I は非同期レプリケーションシステムです。と言うことは、現在のセットのオリジンが故障した場合オリジン側でコミットされた最終のトランザクションはまだサブスクライバに伝播されていないことがほぼ確実です。システムは特に負荷が大きい場合に故障しやすく、マーフィーの法則による自然の結果です。従い、主たる目標はメインサーバの故障を防止することです。最善策は頻繁に保守を行うことです。
システム保守を行う"専門職的"方法の、稼働しているサーバの筐体を開けることは全く私達の考えることではありません。そして面白いことに、バックアップとフェイルオーバのためにレプリケーションを使用することに価値を見出すユーザは、"システム運転停止期間"のようなことに最も忍耐力を所有していない方々そのものです。これらの要求を支援するため、 Slony-I はフェイルオーバ機能のみならず、管理されたオリジン転送の概念を提供します。
このドキュメントは読者が slonik ユーティリティに精通していて、最低限 Slony-I で単純な2ノードによるレプリケーションシステムを如何に設定するか知っていることを前提にしています。
1つの"サブスクライバ"をノード2(例えば:スレーブ)として持つ、現在の"オリジン"のノード1を仮定します。第3のサーバ上にある Web アプリケーションがノード1上のデータベースにアクセスしています。両方のデータベースは稼働中でレプリケーションは通常に同期が取られています。MOVE SET を使用して管理されたスイッチオーバを行います。
このドキュメントの執筆時点では他のサーバへのスイッチオーバはアプリケーションがデータベースに再接続することを必要とします。従い混乱を避けるため、単に Web サーバを停止することにします。アプリケーションでデータベース接続に pg_pool を使用しているユーザは単に pool を停止させるだけです。
小さな slonik スクリプトは以下の命令を実行します。
lock set (id = 1, origin = 1); wait for event (origin = 1, confirmed = 2); move set (id = 1, old origin = 1, new origin = 2); wait for event (origin = 1, confirmed = 2);
これらの命令の後、データセット1のオリジン(マスターの役割)はノード2に移転されました。単に移転されたのではなく、ノード1が完全にサブスクライバと同期し、能動的にそのセットをレプリケートします。ですから2つのノードの役割が完全に交換されました。
Web アプリケーション(もしくは pgpool )がノード2のデータベースに接続するように再構成された後、Web サーバが再稼働され通常の運用に戻ります。
1つのシェルスクリプトで行われたのは、アプリケーションを停止し、slonik を実行し、構成ファイルを移動し、そして全てを一緒に開始する、この全体の手順は10秒以内で完了します。
次に単にノード1をホスティングしているサーバを停止し、サーバの保守に必要なことを何でも行います。後に slon ノード1が再稼働した時点で、レプリケーションが再開され、すぐに状態を捕捉します。この時点でオリジンを交換する手順が当初の構成を復元するため再実行されます。
これは諸事取り扱いに好都合な方法です。管理者の管理下で敏速に実行され、データの壊失もありません。
"オリジン"サーバにより深刻な問題が発生した場合はサーバをバックアップするため FAILOVER が必要かも知れません。これはオリジンでコミットされたトランザクションがサブスクライバに適用されず、データが失われたかなり好ましからざる状況です。結果としてフェイルオーバは最後の頼みの綱と見なされるべきです。もし"手負の"オリジンサーバがふらふらしながらも、管理されたスイッチオーバを行うにかなりの時間を要するとしても、その時点まで戻すことが可能であれば大変好都合です。
Slony-I はシステム障害を自動検出しません。コミット済みのトランザクションを放棄することはデータベースシステムによっては行なうことができない業務上の決断です。ネットワーク監視システムから自動的に実行される命令をスクリプトの下に書き込みたい方が居られれば、うーむ … それはあなたのデータで、それがあなたのフェイルオーバ方針ですね、と言うしかありません。
slonik 命令
failover (id = 1, backup node = 2);
はノード2が現在オリジンとしてノード1が所有する全てのセットの所有権(オリジン)を所有していると仮定します。もしSlony-I クラスタに追加のノードがたまたまあったとすると、ノード1の全ての直接のサブスクライバに出来事があったことが通知されます。同時に Slonik はどのノードが最上のレプリケーション状態にあるかを決定するため全ての直接のサブスクライバにそれぞれのセットに対して問い合わせを行い(例えば:一番新しいコミットされたトランザクション)、ノード2がテーブルへの書き込みアクセスを許可する前に、最初にそれらの最終状態を適用するように構成が変更されます。
さらに、ノード1を直接サブスクライブする全てのノードは、次にノード2をそのセットのデータプロバイダとして使用します。これが意味するのは、フェイルオーバ命令が成功すると全てのレプリケーション設定のどのノードもノード1からもはや何も受け取りません。
ノード2に再接続するためのアプリケーション(もしくは pgpool)の再構成と再起動。
フェイルオーバが完了し、ノード2がテーブルに対して書き込み操作を受け入れた後、ノード1の構成情報の残骸を DROP NODE 命令で全て削除します。
drop node (id = 1, event node = 2);
前に説明したフェイルオーバの後、ノード1上に保存されていたデータは急速にその他のノードとの同期が益々取れなくなり、破壊状態になります。ですから、ノード1を復帰させ、サブスクライバとして最初からオリジンのロールバックをそこに転送する唯一の方法は、追い付かせて、そしてスイッチオーバ手順に従わせることです。
これを自動化させないよい理由として、(業務的観点からの)重要な更新は支障の起こったシステム上でコミットされたであろうという事実に基づきます。もしかすると故障したノードで行われた最後のいくつかのトランザクションを、その内のいくつかを"健全な"ノードで再適用できるかどうかの検証のために分析したいと考えるかも知れません。例えば、誰かが銀行にお金を預けに行って、顧客の口座に影響を及ぼす障害が起こった場合、その時点の情報を失いたくはないですね。
警告 |
もしノードがデータ記憶の障害ではなく、持続的なネットワーク停止に起因した"障害"の場合、非常に困惑した結果が見受けられます。このような筋書きにおいて、"故障した"ノードでは完全に申し分のない形でデータベースが保持されています。以降切り放されてしまっただけで、"無言で金切り声を立てています"。 ネットワーク接続が回復されると、そのノードも回復し、その構成に関するかぎり、全て完全で、Slony-I クラスタのそれ以外と通信できるはずです。 事実、引き起こるたった1つの混乱はそのノード上にあります。クラスタ内のその他のノードは全く混乱しません。このノードが"死んでいる"ことを理解しており、無視するだけです。しかし"故障した"ノードを見ることでこれを知る手がかりはありません。 このことは Slony-I はネットワーク監視ツールではないという設計上の要点に帰着します。どのデータベースホストが使われるかアプリケーションとユーザの通信について明確な筋道を持たなければなりません。もしそれらの筋道が欠けていると、混合システムにレプリケーションを加えることは混乱を来す可能性を増し、フェイルオーバが混乱に対する最大の潜在要素となるでしょう。 |
データベースが巨大な場合、機能する Slony-I ノードとしてのノード1の回復に沢山の時間を要します。 これがフェイルオーバをあまり行いたくはない"最後の手段"とみなしているもうひとつの理由です。