Windows Azure SQL データベースのフォールト トレランス
このポストは、7 月 31 日に投稿された Fault-tolerance in Windows Azure SQL Database の翻訳です。
編集メモ : 今回は、 SQL Server & Windows Azure SQL データベースチームで主任グループプログラムマネージャーを務めるTony Petrossianの投稿を紹介します。この投稿では、Windows Azure SQL データベースのフォールト トレランス機能の概要を説明します。
はじめに
数年前、マイクロソフトのクラウド RDBMS サービスである、Windows Azure SQL データベースの構築を始めた時点で、私たちはフォールト トレランスを、すべてのクラウド データベース サービスの基本要件と見なしていました。マイクロソフトのクラウド サービスのお客様は、ストレージ ソリューションに対する多種多様なニーズをお持ちですが、私たちが着目したのは、アプリケーションに RDBMS を必要とするお客様のニーズに対処することでした。たとえば、当社サービスの早期採用企業の中に、Windows Azure 内で大規模なチケット予約システムを構築していたお客様がいらっしゃいます。そのアプリケーションでは、並行処理制御が可能なリレーショナル機能と、一貫性および持続性によるトランザクションの保証を必要としていました。
実用性の高い RDBMS サービスを構築するには、フォールト トレランスを実現すると同時に、SQL Server データベースに匹敵する ACID (Atomicity: 原子性、Consistency: 一貫性、Isolation: 独立性、Durability: 持続性) 特性を備えたサービスを提供する必要がありました。私たちはさらに、プロビジョニング上の問題を生じさせることなく、お客様が何千ものデータベースを作成および削除できるような柔軟性とスケーリング機能を提供しようと考えました。クラウド規模のフォールト トレラント (FT) システムを構築するには、大幅な技術革新が必要でした。
最初に行ったのは、多種多様な障害のタイプに関する多くのデータを収集し、さまざまなシステム障害モデルの規則性を、時間をかけて詳しく研究することでした。最終的には、幅広い問題を、次の 2 つの原則に絞り込みました。
1.ハードウェア障害とソフトウェア障害は避けられない
2.運用スタッフがミスをすることが、障害につながる
私たちが障害モデルを集約するにあたり、意思決定を後押しした要素が 2 つありました。1 つ目として、フォールト トレラント システムでは、頻度の低い障害、計画的なサービスの停止、および頻度の高い障害に対処することが求められます。2 つ目に、クラウド規模となると、低頻度の障害は、毎日ではないにしても毎週のように発生します。
すべてのコンポーネントは障害を起こす可能性があり、システム内のコンポーネントごとに別々の FT ソリューションを導入するのは現実的でないことを前提に、私たちはフォールト トレランスの設計を始め、少数のソリューションをできるだけ集約しました。たとえば、コンピューター内の全コンポーネントが故障する可能性があるなら、電源装置や RAID といったコンポーネントの冗長化に資金を投じるよりも、コンピューターを冗長化する方がいいことになります。
最終的には、データベースをホストする、データベース サーバーを稼働させるためのフォールト トレラント システムを構築する代わりに、スタックの最上位にフォールト トレラント SQL データベースを構築することに決めました。オペレーターやお客様による、設定や管理を必要としないサービスを提供するうえで、FT 機能は本質的に欠かせないことを忘れてはならないでしょう。
フォールトトレラント SQL データベース
お客様が最も関心を持っているのは自社のデータベースの耐障害性であり、サービス全体の耐障害性はそれほど気にされません。たとえ 99.9% のサービス稼働率を達成しようとも、ダウンした 0.1% のデータベースに "自社のデータベース" が含まれていては意味がないのです。すべてのデータベースはフォールト トレランスを備えている必要があり、障害の軽減策を講じた結果、コミットしたトランザクションが失われることは許されません。フォールト トレラント データベースを実現するうえで、基盤となるテクノロジは主に次の 2 つです。
- データベース レプリケーション
- 障害検出とフェールオーバー
これらのテクノロジを併用することで、人の手を介さず、自動的にデータベースを障害から回復させて被害を軽減すると同時に、ユーザーのデータベースから、コミットされたトランザクションが失われるのを確実に回避できます。
データベースのフォールト トレランスの要旨
Windows Azure SQL データベースでは、全データベースの複数のコピーを、完全に独立した複数の物理サブシステム (サーバー ラックやネットワーク ルーター) に分散された、別々の物理ノードで維持します。Windows Azure SQL データベースでは常に、データベースあたり 3 つのレプリカ (1 つのプライマリ レプリカと 2 つのセカンダリ レプリカ) を維持しています。Windows Azure SQL データベースはクォーラムベースのコミット スキームを使用しており、トランザクションがコミットされたとユーザーが考える前に、プライマリ レプリカおよび 1 つのセカンダリ レプリカにデータが書き込まれます。プライマリ レプリカのいずれかのコンポーネントで障害が発生すると、Windows Azure SQL データベースが障害を検知し、セカンダリ レプリカへのフェールオーバーを実行します。レプリカが物理的に消失した場合は、Windows Azure SQL データベースによって、新たなレプリカが自動的に作成されます。そのため、データ センター内には、トランザクションの一貫性が保たれた、各データベースのレプリカが少なくとも 2 つ存在します。データ センター全体が利用不能となった場合を除き、その他の障害についてはすべて、このサービスによって軽減策が講じられます。
Windows Azure SQL データベースのレプリケーション、障害検出、およびフェールオーバーのメカニズムは完全に自動化されており、人の手を介さずに動作します。このアーキテクチャは、コミットされたデータの消失を確実に防ぎ、データ持続性を最優先する目的で設計されています。
お客様の主なメリット
1.お客様は、複雑なハードウェア、ソフトウェア、OS、仮想化環境などの設定や保守を行うことなく、レプリケーションされたデータベースのメリットをフル活用できます。
2.システムによって、リレーショナル データベースの ACID 特性が完全に維持されます。
3.フェールオーバーは完全に自動化されており、コミットされたデータは一切失われません。
4.プライマリ レプリカへの接続のルーティングはシステムによって動的に管理され、アプリケーション ロジックは必要ありません。
5.高度で自動化された冗長環境が、追加料金なしで提供されます。
さらに関心をお持ちの皆様のために、以降では 2 つのセクションにわたり、レプリケーション テクノロジおよびフェールオーバー テクノロジに関する、マイクロソフト社内での取り組みについて詳しく説明します。
Windows Azure SQL データベースのレプリケーションのしくみ
冗長性はフォールト トレランスの要であり、Windows Azure SQL データベースの中核です。Windows Azure SQL データベース内の冗長性はデータベース レベルで維持されるため、それぞれのデータベースは物理的および論理的に冗長化されます。各データベースの冗長化は、データベースのライフサイクル全体を通じて適用されます。データベースはすべて、実際に提供および使用される前に複製され、こうしたレプリカは、お客様がデータベースを削除するまで維持されます。データベースの 3 つのレプリカはそれぞれ、別のノードで保管されます。各データベースのレプリカは、2 つのコピーが同じ "障害を起こしたドメイン" (同じネットワーク スイッチの下位や同じラック内) に集中しないよう、複数のノードに分散されます。同じお客様が複数のデータベースを所有している場合でも、各データベースのレプリカをノードに割り当てる際は、他のデータベースのレプリカとは別に割り当て処理を行います。つまり、ある 2 つのデータベースのレプリカが同一のノードに格納されていても、それらのデータベースの別のレプリカが、同じように別のノード上に一緒に格納されるわけではありません。
どのデータベースでも、常に 1 つのレプリカがプライマリに指定されます。トランザクションの実施には、データベースのプライマリ レプリカ (略してプライマリ データベース) が使用されます。プライマリ レプリカは、クエリ、更新、およびデータ定義言語の処理のすべてに対応します。プライマリ レプリカは、Windows Azure SQL データベースのレプリケーション プロトコルを使用して、更新およびデータ定義言語の処理結果をセカンダリ レプリカへと転送します。このシステムでは現在、セカンダリ レプリカの読み取りを許可していません。トランザクションによる読み書きは、すべてプライマリ データベースを使用して実施されるため、このプライマリ パーティションに直接アクセスするノードが、データに対する処理のすべてを実行します。対象のノードは、更新されたレコードをデータベースのセカンダリ レプリカに送信し、各レプリカで更新が適用されます。セカンダリ レプリカは読み取り処理に対応しないため、セカンダリ レプリカと比べ、プライマリは多くの処理を実行します。負荷のバランスを取るため、各ノードがホストするデータベースには、プライマリとセカンダリを混在させています。平均すると、3 ウェイ レプリケーションの場合、ノードあたり、セカンダリ レプリカ 2 つごとにプライマリ 1 つの割合でデータベースをホストします。当然、1 つのデータベースの 2 つのレプリカが、同一の物理ノード上で一緒に格納されることはありません。
各ノードがホストするデータベースに、プライマリとセカンダリを混在させることのもう 1 つの利点は、障害が起きたノードの負荷を、多くの正常なノードに分散させられることです。たとえば、ノード S が、PE、PF、および PG という 3 つのプライマリ データベースをホストしているとします。S で障害が発生しても、PE、PF、PG のセカンダリ レプリカが別々のノードに分散されていれば、PE、PF、PG の新たなプライマリ データベースを、3 つの異なるノードに割り当てることができます。
レプリケーション プロトコルは、このクラウド専用に構築されており、(コンポーネント障害は避けられないため) 信頼できないことが前提となるハードウェア コンポーネントとソフトウェア コンポーネントを集約したクラウドの、安定した運用を実現します。このトランザクションのコミット プロトコルを使用するには、レプリカのクォーラムのみが有効化されている必要があります。レプリカのセットの維持には、Paxos と同様のコンセンサス アルゴリズムを使用しています。また、多重障害に備え、可用性を維持するためにダイナミック クォーラムを使用しています。
プライマリからセカンダリへの更新内容の伝達は、レプリケーション プロトコルによって管理されます。まず、トランザクション T のプライマリ データベースが、T によって行われた各更新の処理後のイメージを含むレコードを生成します。この更新レコードは、処理を元に戻すための論理レコードの役割を果たし、ページ ID ではなくテーブル キーによって識別されます。生成された更新レコードは、順次セカンダリ レプリカへと送信されます。T を中止すると、プライマリが各セカンダリに ABORT メッセージを送信し、T について受信した更新データが、セカンダリによって削除されます。T が COMMIT 処理を実行すると、プライマリは T に次のコミット シーケンス番号 (CSN) を割り当て、セカンダリ レプリカへと送信される COMMIT メッセージにタグが付けられます。各セカンダリは T の更新データを、T に対応する独立したローカル トランザクションのコンテキスト内で、コミット シーケンス番号の順にデータベースへと適用し、受信確認 (ACK) メッセージをプライマリに送信します。プライマリは、レプリカのクォーラム (プライマリ自体を含む) から ACK を受信すると、ローカルで永続的な COMMIT レコードを書き込み、T の COMMIT 処理に対して "成功" を返信します。セカンダリでは、トランザクション T の COMMIT メッセージを受信した直後に ACK を返信してから、先行して受信した、T の対応するコミット レコードおよび更新レコードをログに適用できます。そのため、T がコミットする前に、ノードのクォーラムがコミット後のコピーを保持していることになります。
更新されたレコードは最終的に、プライマリ レプリカおよびセカンダリ レプリカによってディスクに書き出されます。これは、プライマリ レプリカとセカンダリ レプリカの差を最小限にし、フェールオーバー イベントの間に、データが失われる可能性を減らすことを目的としています。
コミットされたトランザクションの更新データが、(クラッシュなどのために) セカンダリで失われた場合には、プライマリ レプリカから取得できます。この場合、回復対象のレプリカは、最後にコミットしたトランザクションのコミット シーケンス番号をプライマリに送信します。プライマリは応答として、回復対象のレプリカが必要とする更新データのキューを送信するか、差異が大きすぎて追跡できないことを通知します。後者の場合、回復対象のレプリカは、プライマリに対して新しいコピーの転送を要求できます。セカンダリは、プライマリ ノードから受信した更新データをすぐに適用するため、常に最新に近い状態が維持されます。そのため、(負荷分散やプライマリでの障害のために) 構成変更が発生し、セカンダリがプライマリとなる必要がある場合でも、ほぼ瞬時に再割り当てを完了できます。このように、セカンダリ レプリカはホット スタンバイとして、可用性向上に大きく貢献しています。
障害検出とフェールオーバーのしくみ
大規模な分散処理システムでは、信頼性に優れた障害検出システムを実装し、確実かつ迅速に、できるだけお客様の近くで障害を検出できるようにする必要があります。Windows Azure SQL データベースの分散処理ファブリックは、SQL エンジンと連携することにより、データベースに近い場所で障害を検出できます。
非常に大規模なシステムの場合、稼働状況の監視を一元化するのは非効率であり、信頼性も低下します。Windows Azure SQL データベースの障害検出機能は完全に分散されているため、システム内の任意のノードを、複数の隣接ノードで監視できます。このトポロジにより、きわめて効率的かつ局所的で、高速な検出モデルが実現され、よくあるような ping ストームや、障害検出の不要な遅れを回避できます。
障害については、後から分析するために、詳細なコンポーネントレベルのデータを遠隔測定によって収集していますが、フェールオーバーに関する決定を下す場合は、ファブリックによって検出された、障害の大きな特徴のみを使用します。マイクロソフトは長年にわたり、ノード障害の発生によってパフォーマンスが低下した状態が長引かないよう、Fail Fast および回復の機能向上に取り組んできました。
Windows Azure SQL データベースでは、フェールオーバーの単位がデータベースとなるため、それぞれのデータベースの稼働状況を注視し、必要に応じてフェールオーバーを行っています。Windows Azure SQL データベースでは、Global Partition Manager (GPM) 内で、全データベースおよび対応するレプリカのグローバルなマップを維持しています。このグローバル マップには、各データベースおよびそのレプリカの、健全性、状態、場所が含まれます。グローバル マップの保守は、分散処理ファブリックが行っています。Windows Azure SQL データベースのノードに障害が発生すると、分散処理ファブリックが確実かつ迅速にノードの障害を検出して GPM に通知します。その後 GPM は、障害が発生したノード上にある、プライマリ データベースとセカンダリ データベースの割り当てを再構成します。
Windows Azure SQL データベースの運営には、レプリカのクォーラムのみがあれば足りるため、セカンダリ レプリカの障害は可用性に影響を及ぼしません。バックグラウンドでは、障害の起きたレプリカの代わりに、新たなレプリカが自動的に作成されます。
ごく短時間、一時的にレプリカが利用できなくなっただけの場合は、受信しそこなった少数の不足トランザクションを、後から補うだけで済みます。対象のノードは、稼働中のレプリカに対し、ノードのダウン中にレプリカが受信しそこなった、更新キューの最後の部分を送信するよう要求します。どうしても必要でない限り、一時的に利用不能になったセカンダリ レプリカについては、簡易的な同期を許可し、レプリカを完全に作成し直すのを避ける方が適切です。
プライマリ レプリカに障害が発生した場合は、セカンダリ レプリカの 1 つを新しいプライマリに指定し、その決定に基づいて、使用可能なすべてのレプリカを再構成する必要があります。このプロセスは、GPM を利用して、データベース構成を再構築するためのリーダーを選択することから始まります。選択されたリーダーは、レプリカ セットを構成する全メンバーへの通信を試みて、更新データが失われていないことを確認します。リーダーは、どのセカンダリが最新の状態であるかを判断します。最新の状態のセカンダリ レプリカは、いくつかの変更が欠けている他のレプリカに対し、要求された変更データを渡します。
Windows Azure SQL データベース内では、データベースに対する接続がすべて、負荷分散された一連のゲートウェイ プロセスによって管理されます。ゲートウェイは、クライアントから受信するデータベースへの接続要求を受け入れて、現在データベースのプライマリ レプリカをホストしているノードへとバインドする役割を果たします。ゲートウェイは分散処理ファブリックと連携し、お客様のデータベースのプライマリ レプリカがどこにあるかを突き止めます。フェールオーバーが発生すると、新しいプライマリが利用可能になり次第、障害が発生したプライマリにバインドされていた全接続について、ゲートウェイが再ネゴシエーションを実行して新しいプライマリへと接続をバインドします。
接続ゲートウェイ、分散処理ファブリック、および GPM を組み合わせることで、障害を検出すると共に、Windows Azure SQL データベースによって維持されたデータベース レプリカを使って、障害を軽減することが可能となります。