DAL – RDBMS のシャーディング
このポストは、9 月 6 日に投稿された DAL – Sharding of RDBMS の翻訳です。
編集メモ : 今回は、クラウドおよびエンタープライズ グループで AzureCAT プログラムのシニア マネージャーを務める Shaun Tinline-Jones と Chris Clayton による記事をご紹介します。
「Cloud Service Fundamentals (英語)」アプリケーション (別名「CSFundamentals」) は、データベースをバックエンドとする Azure サービスの構築方法を説明するためのものです。内容としては、シナリオ、実装アーキテクチャ、そしてログ記録に再利用可能なコンポーネント、構成やデータ アクセスの説明が含まれています。このコード ベースは、運用環境への展開を前提に、Windows Azure で高可用性かつスケーラブルなサービスを配信するためのベスト プラクティスを実際に体験していただけるよう、Windows Azure カスタマー アドバイザリー チームが作成しました。
現在では、たいへん多くの企業の皆様がクラウドの活用を推し進めていることから、ソリューションに求められるニーズは、コストの削減、俊敏性の向上、スケールの拡大など、非常に多様化しています。たとえば、「クラウド スケール」の達成を目標とするソリューションでは、その戦略が、ハードウェアのアップグレードによって容量を増加させる「垂直スケール」から、特定のタスクを共有するコンピューターの数を増加させる「水平スケール」へと変化しています。このトレードオフのよい例が、Web ファームの作成です。Web ファームでは、ある負荷の処理を 1 台のマシンが単独で行うのではなく、同一の Web サイトのコンテンツを多数のサーバーで処理します。
コンピューティング ノードに水平スケーラビリティを導入する計画を開始しても、リレーショナル データベース管理システム (RDBMS) やキャッシュなどの、特に複雑で、深刻な緊急事態を引き起こす可能性のある階層については、着手しない場合がほとんどです。これらのサービスでは、入出力処理が激しく実行され、また単一のインスタンスに統括されていることが多々あります。水平スケーラビリティをこのような状態の階層に実装する手法の 1 つに、「シャーディング」があります。シャーディングとは、RDBMS のデータを複数のデータベースに論理的に分割する方法です。このとき、通常は同一のスキーマが使用されます。たとえば、この手法を使用すると、従業員テーブルを別々の 3 つのデータベースに分割し、それぞれのデータベースに異なる部署の従業員を格納することができます。
シャーディングは、単純な容量関連のシナリオ以外でも大きなメリットがあります。この記事では、Azure SQL データベースに実装されていて、主に OLTP サービスを提供している RDBMS に対してシャーディングを行います。データベース構造にシャーディングを採用した場合、次のようなシナリオでメリットが得られます。
- 制限のしきい値またはスループット制限に頻繁に達する場合
- データベースが肥大化して扱いづらい場合 (インデックス、再構築、バックアップ)
- データベースの 1 つが使用不能になり、それがすべてのユーザーに影響を与えている場合 (シャード 1 つの場合と逆)
- 需要に応じて柔軟にスケール アップやスケール ダウンをすることが困難なデータベースの場合
- マルチテナントや SaaS の提供など、特定のビジネス モデルの場合
Windows Azure SQL データベースなど、サービス ソリューションとしてマルチテナント データベースを使用する場合は、サービス品質 (QOS) の管理が導入され、さまざまな条件下でクライアントの制限が実施されます。通常この制限は、リソースの圧迫が強まったときに実施されます。シャーディングは、ある負荷が単一のサーバーに影響を与え、それが複数のサーバー (各サーバーにはシャードが存在) に影響を広めているときに、その負荷を負担し、リソースの圧迫を軽減する場合に使用される主要な戦略です。たとえば、1 つの均一な配布を想定した場合、5 つのシャードを作成すると、各データベースの負荷は約 20% に軽減されます。
大幅な機能強化の代償として、デメリットもあります。シャーディングでは、一部の重要な領域が複雑化することが避けられないため、以下のような点について、計画をより確実に作成する必要があります。
- 業務上、将来的にシャード数を減らすことが必要になった場合を想定して、すべてのシャードで ID 列をグローバルに一意にする必要があります。シャード全体で ID が一意でない場合、2 つのシャードを統合するときに競合が発生する可能性があります。
- 個々のシャードが独立したデータベースであるため、参照整合性によって行のリレーションシップを参照したり強制したりすることができません。
- シャードをまたぐクエリを発行すると、各シャードに対してクエリを実行し、その結果を統合する必要が出てくるため、可能な限り使用を避けます。シャードをまたいで「展開」クエリを実行することは、パフォーマンスの面で好ましくないだけではなく、それをサポートするとシャーディング フレームワークがより複雑になります。シャードをまたぐクエリの実行が必要な場合は、通常、各シャードに非同期でクエリを発行します。ただし、同期処理を行う方が結果セットのサイズを管理しやすい場合もあります。
多くの場合、シャーディングは、上位レベルのアプリケーション ロジックで複雑な部分をほとんど抽象化し、データ アクセス層 (DAL) で行います。
シャード化アーキテクチャの構築において、「テナント」をどのように定義するかということは、最重要決定事項の 1 つです。テナントは、データの一意な分類としては最も大きなもので、同一のシャード上に存在することが保証されています。1 つのテナントに制限されているクエリは、通常の動作状態では展開動作が不要なため、通常はパフォーマンスが優れています。適切にテナントを定義するには、以下のような要素を考慮する必要があります。
- 上位レベルのアプリケーション コードの識別子の認識レベル
- 当該レベルで実行される最も中核的なビジネス トランザクションの能力
- テナントの粒状性において、一般的な通常業務の制限を回避する能力
Windows Azure カスタマー アドバイザリー チームは、このような高いレベルの概念や考慮事項を提示するために、Cloud Services Fundamentals (CSF) パッケージ (https://code.msdn.microsoft.com/Cloud-Service-Fundamentals-4ca72649、英語) に基礎的なシャーディング用データ アクセス層 (DAL) を構築しました。
CSF では、テナントは個別のユーザーとして定義されています。このテナントを選択する要素としては、以下が挙げられます。
- 中核的なビジネス要件の多くでは、複数ユーザーにまたがるクエリが不要です。
- 使用不能なシャードが影響を与える範囲は定義されたユーザー群のみで、他のすべてのユーザーは通常どおりシステムを使用し続けることができます。1 つのシャードのユーザー数は、業務に耐えられる範囲で調整できます。
このテナントは、データベース間のトランザクションが不要になるように定義および実装してあります。図 1 では、このデータ セットは、データ モデル トランザクション境界という名前のシャードレットとなっています。
図 1: データモデルトランザクション境界
ユーザーが特定のセッションで最初にデータベースに接続したときに、簡単なクエリ群が実行されます。これによって、オフラインのシャードの影響で使用できない機能がないかどうかが確認されます。
CSF のデモで示しているように、シャーディングの手法を簡略化する取り組みの一環として、マイクロソフトは予見できる範囲の将来までの容量に対するニーズに対応できるように、十分なストレージを持つシャード群を作成することを決定しました。このサイズに決定したことにより、テナントの移動などの操作を含む、シャード数の増減のデモが不要になりました。テナント名をハッシュ化する際に整数が生成され、この ID が「シャード マップ」内の適合範囲の参照に使用されます。CSF では範囲ベースのメカニズムが使用されており、一定範囲の数が特定のシャードに割り当てられ、「シャード マップ」に取得されます。
シャード セットにシャードを追加したり、削除したりするイベントでは、新しいシャードに切り替えるまでの間、テナントの使用を停止する必要があります。この重大な制限があることを考慮して、複雑なシャード管理の手間を減らすか、または不要にするために、シャード セットは最初の作成時に過剰にプロビジョニングしておくことが必要です。
このソリューションでは、データ アクセス層 (DAL) がテナント ID を認識していて、シャード セット内の場所を特定できることが要件となっています。使用不能のシャードが含まれるクエリが実行されると、クエリ全体が失敗します。DAL にテナント ID が含まれていないイベントでは、すべてのシャードに対してクエリを実行する必要があり、これにより失敗の可能性が高まるほか、パフォーマンスも低下します。
高度なシャーディング手法を説明するためのコード サンプルの公開については、現在、準備を進めています。このサンプルでは、以下の分野について改善策を提供する予定です。
- 事前対応および事後対応のシャード管理
- グローバルな一意性と ID の管理
- 同一セット内でのシャード間のテナント移行
- シャード セットの拡張、縮小
- テナントを認識していないクエリの改善
Cloud Services Fundamentals コード サンプルは、「クラウド スケール」のアプリケーションを作成するうえで非常に重要な手法であるシャーディングの基礎的な概念に触れていただくきっかけとして非常に有効です。ぜひお試しください。