次の方法で共有


シャーディング パターン

データ ストアを水平方向のパーティションまたはシャードのセットに分割します。 この方法では、大量のデータを格納してアクセスするときのスケーラビリティを向上させることができます。

コンテキストと問題

単一サーバー上のデータ ストアには、次の制限があります。

  • ストレージ領域: 大規模なクラウド アプリケーションのデータ ストアには、時間の経過と同時に増加する大量のデータを含めることができます。 サーバーには有限のディスク 記憶域が用意されており、既存のディスクを大きなディスクに置き換えたり、データ ボリュームの増加に合わせてディスクを追加したりできます。 システムは最終的に上限に達し、1 台のサーバーでストレージ容量を増やすことはできません。

  • コンピューティング リソース: クラウド アプリケーションでは、データ ストアに対してクエリを実行する多数の同時実行ユーザーをサポートする必要があります。 1 台のサーバーでは、この負荷に対して十分なコンピューティング能力が提供されないため、応答時間とタイムアウトが長くなります。 メモリまたはアップグレード プロセッサを追加できますが、システムは上限に達しますが、コンピューティング リソースをさらに増やすことはできません。

  • ネットワーク帯域幅: 1 台のサーバーが要求を受信して応答を送信できる速度によって、データ ストアのパフォーマンスが制限されます。 ネットワーク トラフィックの量がネットワーク接続の容量を超える可能性があり、要求が失敗します。

  • 地理: 法的要件、コンプライアンス要件、またはパフォーマンス要件では、ユーザーと同じ地理的リージョンにユーザー データを格納することが必要になる場合があります。 ユーザーが複数の国/地域にまたがる場合、アプリケーションのすべてのデータを 1 つのデータ ストアに格納できない可能性があります。

これらの制限を一時的に延期するには、ディスク容量、処理能力、メモリ、ネットワーク接続を追加することで、垂直方向にスケーリングできます。 多数のユーザーと大量のデータをサポートする必要があるクラウド アプリケーションは、水平方向にスケーリングする必要があります。

ソリューション

データ ストアを水平方向のパーティションやシャードに分割します。 各シャードには同じスキーマがありますが、データの独自の個別のサブセットが含まれています。 各シャードは、さまざまな種類の多数のエンティティのデータを含むことができる完全なデータ ストアです。 シャードは、ストレージ ノードとして機能するサーバー上で実行されます。

このパターンには次のような利点があります。

  • 追加のストレージ ノードにシャードを追加することで、システムをスケールアウトできます。

  • システムは、記憶域ノードごとに特殊で高価なコンピューターではなく、事前構築済みのハードウェアを使用できます。

  • シャード間でワークロードをバランスさせることにより、競合を減らし、パフォーマンスを向上させることができます。

  • クラウドでは、シャードは、データにアクセスするユーザーの近くに物理的に存在できます。

データ ストアをシャードに分割する場合は、各シャードに配置するデータを決定します。 各シャードは、通常、1 つ以上のデータ属性でグループ化された項目を保持します。 これらの属性はシャード キーを形成し、 パーティション キーと呼ばれることもあります。

シャーディングにより、データは物理的に整理されます。 アプリケーションがデータを格納して取得すると、シャーディング ロジックによって適切なシャードに転送されます。 このロジックは、アプリケーションのデータ アクセス コードに実装することも、シャーディングを透過的にサポートしている場合はデータ ストレージ システムに実装することもできます。

シャーディング ロジック内のデータの物理的な場所を抽象化すると、どのシャードにどのデータが含まれているかを制御できます。 また、シャードが不均衡になった場合など、データを再配布する必要がある場合に、アプリケーション ビジネス ロジックを変更せずにシャード間でデータを移行することもできます。 トレードオフは、取得中に各データ項目の場所を決定するための追加のデータ アクセスオーバーヘッドです。

シャード キーの選択

シャード キーは、シャード 化されたシステムで最も重要な設計上の決定です。 シャード キーを選択した後で変更するには、通常、すべてのデータを新しいシャード レイアウトに移行する必要があります。これは、ライブ システムでのコストとリスクの高い操作です。 コードを記述する前に、この決定を慎重に行ってください。

効果的なシャード キーは不変であり、カーディナリティが高く、データを分散して均等に読み込み、主要なクエリ パターンに合わせて調整されるため、ほとんどの要求が 1 つのシャードに対して解決されます。 値 (自動インクリメント整数とシーケンシャル タイムスタンプ)、カーディナリティの低い属性 (ブール値と小さい列挙型セット)、および頻繁に変更される揮発性属性は、単調に増加しないようにします。 これらの属性は、ホットスポットやコストのかかるシャード間のデータ移動につながります。

これらの条件を満たす属性が 1 つもない場合は、2 つ以上の属性を組み合わせて複合シャード キーを定義します。 クエリがシャード キーの一部ではない属性によってデータを取得する必要がある場合は、 インデックス テーブル パターンなどのパターンを使用してセカンダリ参照を提供します。

Azure サービス間でパーティション キーを選択する方法の詳細については、 データパーティション分割のガイダンスデータパーティション分割戦略に関するページを参照してください。

シャーディング戦略

シャード キーを選択し、シャード間でデータを分散する方法を決定するときは、次のいずれかの方法を使用します。 シャードとそれをホストするサーバーの間に1対1の対応は必要ありません。 1 つのサーバーで複数のシャードをホストできます。

ルックアップ シャーディング戦略

検索戦略 ( ディレクトリベースの戦略とも呼ばれます) では、シャーディング ロジックは、シャード キーを使用してそのデータを含むシャードにデータ要求をルーティングするマップを実装します。 マルチテナント アプリケーションでは、テナント ID をシャード キーとして使用して、テナントのすべてのデータをシャードにまとめて格納できます。 複数のテナントが同じシャードを共有する場合がありますが、1 つのテナントのデータは複数のシャードに分散されません。 次の図は、テナント ID に基づくテナント データのシャーディングを示しています。

テナント ID に基づくテナント データを示す図

シャード キーの値と物理ストレージの間のマッピングは、各シャード キー値が物理パーティションにマップされる直接の場合があります。 より柔軟な手法として、仮想パーティション分割があります。この場合、シャード キーの値は仮想シャードにマップされ、システムはそれらの仮想シャードをより少ない物理パーティションにマップします。 アプリケーションは、仮想シャードを参照するシャード キー値を使用してデータを検索し、システムは仮想シャードを物理パーティションに透過的にマップします。 仮想シャードと物理パーティションの間のマッピングは、アプリケーション コードを変更しなくても変更できます。

範囲ベースのシャーディング戦略

範囲ベースの戦略では、関連する項目が同じシャードにグループ化され、シーケンシャル シャード キーごとに並べ替えられます。 この戦略は、範囲クエリを使用して項目のセットを頻繁に取得するアプリケーションをサポートします。 範囲クエリは、特定の範囲内にあるシャード キーのデータ項目のセットを返します。

たとえば、アプリケーションが特定の月に行われたすべての注文を定期的に検索する必要がある場合、日付と時刻の順序で 1 か月間のすべての注文を同じシャードに格納すると、データをより迅速に取得できます。 各注文を異なるシャードに格納する場合、アプリケーションは個別にフェッチする必要があり、多数のポイントクエリを実行しなければなりません。 次の図は、シャードに格納されているデータのシーケンシャル セット (範囲) を示しています。

シャードに格納されているデータのシーケンシャル セット (範囲) を示す図。

この例では、シャード キーは、注文月を最も重要な要素として含み、その後に注文日と時刻が続く複合キーです。 新しい注文は作成されてシャードに追加される過程で自動的に並べ替えられます。

一部のデータ ストアでは、2 部構成のシャード キーがサポートされています。 パーティション キーはシャードを識別し、行キーはシャード内の項目を一意に識別します。 通常、シャードは行キーの順序でデータを格納します。 範囲クエリを必要とし、グループ化する必要がある項目の場合は、パーティション キーに同じ値を持ち、行キーに一意の値を持つシャード キーを使用できます。

ハッシュベースのシャーディング戦略

ハッシュベースの戦略により、負荷が不均衡な量を受け取るシャードであるホットスポットが発生する可能性が低下します。 この戦略では、各シャードのサイズと各シャードで発生する平均負荷のバランスを取るために、シャード間でデータが分散されます。 シャーディング ロジックにより、1 つ以上のデータの属性のハッシュに基づいて、項目をシャードに格納するよう計算されます。 選択したハッシュ関数は、シャード間でデータを均等に分散する必要があります。 次の図は、テナント ID のハッシュに基づくテナント データのシャーディングを示しています。

テナント ID のハッシュに基づくテナント データのシャーディングを示す図。

他のシャーディング戦略よりもハッシュ戦略の利点を理解するには、新しいテナントを順番に登録するマルチテナント アプリケーションが、データ ストア内のシャードにテナントを割り当てる方法を検討してください。 範囲戦略を使用すると、テナント 1 から n のデータはシャード A に格納され、テナント n+ 1 から m のデータはシャード B に格納され、それ以降のテナント範囲は連続するシャードにマップされます。 最近登録されたテナントも最もアクティブな場合、ほとんどのデータ アクティビティは少数のシャードで発生し、ホットスポットが発生する可能性があります。 これに対し、ハッシュ戦略では、テナント ID のハッシュに基づいてテナントがシャードに割り当てられます。 ハッシュは通常、さまざまなシャード間でシーケンシャル テナントを分散し、負荷を分散します。 前の図は、テナント 55 と 56 に対するこのアプローチを示しています。

地理的シャーディング戦略

地理的戦略では、そのデータの地理的な発生元または使用目的のリージョンに基づいて、データがシャードに割り当てられます。 多くのワークロードでは、ユーザーと生成されるデータが特定のリージョンに集中しています。 データ所在地の法律などの規制要件では、特定のデータを特定の管轄内に留める必要がある場合があります。 規制ドライバーがなくても、最も頻繁にアクセスするユーザーの近くにデータを配置すると、読み取りと書き込みのネットワーク待機時間が短縮されます。

アプリケーション インスタンスの地理的な場所に基づくシャーディング データを示す図。

この戦略では、ユーザーの国/地域、発信元のデータセンター リージョン、リージョン テナント識別子などの地理的属性からシャード キーを派生させます。 各シャードは、その地理的境界内のインフラストラクチャでホストするか、固定します。

たとえば、北米、ヨーロッパ、Asia-Pacific の顧客にサービスを提供するアプリケーションでは、対応する Azure リージョンごとに 1 つのグループである 3 つのシャード グループを保持できます。 ヨーロッパのユーザーのみにサービスを提供するヨーロッパのアプリケーションは、ヨーロッパのシャードに要求をルーティングします。 この方法により、待機時間が短縮され、データ所在地の要件が満たされます。

地理的シャーディングでは、データ分散が不均等なリスクが生じます。 ほとんどのユーザーが 1 つのリージョンに存在する場合、そのリージョンのシャードは負荷とストレージの不均衡な共有を保持します。 地理的シャーディングを、各リージョン内のハッシュやルックアップなどの別の戦略と組み合わせて、同じ地理的境界内の複数のシャードに均等に負荷を分散させることができます。

各戦略の利点と考慮事項

4 つのシャーディング戦略には、次の利点と考慮事項があります。

  • ルックアップ戦略では、 シャード構成をより詳細に制御できます。 仮想シャードは、ワークロードのバランスを取るために新しい物理パーティションを追加できるため、再調整の影響を軽減します。 アプリケーション コードに影響を与えずに、仮想シャードとその物理パーティション間のマッピングを変更できます。 シャードの場所を検索すると、オーバーヘッドが増加します。

  • 範囲戦略は 実装が簡単で、範囲クエリに対して適切に機能します。 範囲クエリでは、1 回の操作で 1 つのシャードから複数のデータ項目を取得できます。 データ管理は簡単です。 たとえば、同じリージョンのユーザーがシャードを共有する場合に、ローカルの読み込みパターンに基づいてタイム ゾーンごとに更新をスケジュールできます。 ただし、この戦略では、シャード間で負荷が均等に分散されることはありません。 再調整は困難であり、ほとんどのアクティビティが隣接するシャード キーに集中している場合、不均一な負荷を解決できない可能性があります。

  • ハッシュ戦略を 使用すると、データと負荷分散の可能性が高くなります。 マップを維持せずにハッシュ関数を使用して、要求を直接ルーティングできます。 ハッシュを計算すると、オーバーヘッドが発生します。 リバランシングは、一貫性のあるハッシュ化なしでは困難です。

  • 地理的戦略は、 他の戦略が本質的に対処していないデータ所在地と主権の要件を満たしています。 これにより、ユーザーが自分のリージョンのデータにアクセスするときの読み取りと書き込みの待機時間が短縮されます。 ただし、地域に基づくシャーディングでは、ユーザー数がリージョン間で均等に分散されていない場合に、データと負荷の不均衡が発生する可能性があります。 グローバル レポートなどのリージョンにまたがるクエリでは、すべての地理的シャードからデータを取得し、待機時間を長くする必要があります。 コンプライアンスと負荷分散の両方が必要な場合は、地理的シャーディングを各リージョン内の別の戦略と組み合わせます。

ほとんどのシャーディング システムでは、これらのアプローチのいずれかを実装しますが、アプリケーションのビジネス要件とそのデータ使用パターンも考慮する必要があります。 たとえば、マルチテナント アプリケーションでは次のような点を考慮します。

  • ワークロードに基づいてデータをシャード化できます。 揮発性の高いテナントのデータを別々のシャードに分離して、他のテナントのデータ アクセス速度を向上させます。

  • テナントの場所に基づいてデータをシャード化できます。 特定の地域のテナント データをオフラインにして、そのリージョンのピーク外の時間帯にバックアップとメンテナンスを行い、他のリージョンのテナント データは営業時間中もオンラインのままです。

  • 価値の高いテナントに専用かつ低負荷のシャードを割り当てます。 価値の低いテナントでは、より密にパックされたシャードを共有できます。

  • 強力なデータ分離とプライバシーを必要とするテナントのデータを別々のサーバーに格納します。

各戦略のスケーリングとデータ移動操作

シャーディング戦略ごとに、スケールイン、スケールアウト、データ移動、状態のメンテナンスを管理するためのさまざまな機能と複雑さのレベルが提供されます。

  • ルックアップ戦略 により、オンラインまたはオフラインのユーザー レベルでのスケーリングとデータ移動操作が可能になります。 データを移動するには:

    1. 一部またはすべてのユーザー アクティビティを一時停止します (通常、ピーク時以外の期間)。

    2. 新しい仮想パーティションまたは物理シャードにデータを移動します。

    3. マッピングを更新します。

    4. このデータを保持するキャッシュを無効または更新します。

    5. ユーザー アクティビティを再開します。

    多くの場合、この操作は一元的に管理できます。 ルックアップ戦略では、状態が高いキャッシュ性を持ち、レプリカフレンドリーである必要があります。

  • 範囲戦略では 、通常、データ ストアの一部または全部がオフラインである間に、シャード間でデータを分割およびマージする必要があるため、スケーリングとデータ移動操作が制限されます。 シャードを再調整するためにデータを移動する場合、ほとんどのアクティビティが隣接するシャード キーまたは同じ範囲内のデータ識別子に集中している場合、不均一な負荷を排除できないことがあります。 範囲戦略では、範囲を物理パーティションにマップするために状態が必要になる場合もあります。

  • ハッシュ戦略では、 スケーリングとデータ移動操作が複雑になります。 パーティション キーは、シャード キーまたはデータ識別子のハッシュです。 hash(key) mod Nなどの標準ハッシュ関数を使用すると、シャードを追加または削除すると、ほとんどのキーが再割り当てされ、大規模なデータ移行がトリガーされます。 一貫性のあるハッシュを使用すると、シャード数が変更されたときにキーのごく一部のみが移動するようにハッシュ空間を配置することで、この影響が軽減されます。 ハッシュ戦略では、個別のマッピング状態のメンテナンスは必要ありません。

  • 地理的戦略は、 スケーリング操作をリージョンのインフラストラクチャ プロビジョニングに直接リンクします。 あるリージョンに容量を追加しても、別のリージョンの負荷は軽減されません。 地理的シャーディングを要求する規制要件により、地理的境界を越えたデータ移動を制限することもできます。 各リージョン内でスケーリングでは、そのリージョンのシャード間でデータを分散するセカンダリ戦略が使用されます。

問題と考慮事項

このパターンを実装する方法を決定するときは、次の点を考慮してください。

  • 垂直方向のパーティション分割や機能パーティション分割など、他の形式のパーティション分割に補完的なシャーディングを使用します。 たとえば、1 つのシャードに垂直方向にパーティション分割されたエンティティを含め、機能パーティションを複数のシャードとして実装できます。 詳細については、「 水平、垂直、および機能データのパーティション分割」を参照してください。

  • すべてのシャードが同様の入出力 (I/O) ボリュームを処理できるように、それらのバランスを均等に保ちます。 データ スキューは、レコードが挿入および削除されると時間の経過と同時に蓄積され、ホットスポットにつながります。 定期的に再調整を計画します。

    再調整はシャード間でデータを移動し、多くの場合、ダウンタイムやスループットの低下を引き起こします。 再調整の頻度を減らすには、仮想パーティションを使用します。 多数の論理パーティションをより少ない物理シャードにマップします。 シャードがオーバーロードされたら、データセット全体を再ハッシュせずに、仮想パーティションを新しい物理シャードに再配布します。 Azure Cosmos DB では、このアプローチを使用して、物理インフラストラクチャからパーティション構成を分離します。

    小さなシャードを多数使用することを、少数の大きなシャードより好みます。 シャードのサイズを小さくすると、移行速度が速くなり、負荷がより均等に分散され、データ再配布の柔軟性が向上します。

  • シャード キーには安定したデータを使用します。 シャード キーが変更された場合は、対応するデータ項目をシャード間で移動することが必要になる場合があります。これにより、更新操作のオーバーヘッドが増加します。 不安定な情報にシャードキーを基づけることは避けてください。 不変または自然にキーを形成する属性を選択します。

  • シャード キーは必ず一意である必要があります。 たとえば、自動増分されるフィールドをシャード キーとして使用しないでください。 システムによっては、自動作成されたフィールドをシャード間で調整できないため、異なるシャード内のアイテムに同じシャード キーが設定される可能性があります。

    シャード キーではない他のフィールドに自動インクリメントされた値も問題を引き起こす可能性があります。 たとえば、オートインクリメントフィールドを使用して一意の ID を生成する場合、異なるシャード内の 2 つの項目に同じ ID が割り当てられる可能性があります。

  • 最も頻繁に実行されるクエリをサポートするためにデータをシャードします。 データに対するすべてのクエリの要件に一致するシャード キーを設計できない場合があります。 必要に応じて、シャード キーの一部ではない属性によってデータを取得するクエリをサポートするセカンダリ インデックス テーブルを作成します。 詳細については、「 インデックス テーブルパターン」を参照してください。

  • ほとんどの操作を 1 つのシャードにスコープするようにシャード キーとデータ モデルを設計します。 1 つのシャードにのみアクセスするクエリは、複数のシャードからデータを取得するクエリよりも効率的です。 データを非正規化して、顧客とその注文など、一般的に一緒にクエリされる関連エンティティを同じシャードに保持し、個別の読み取りの数を減らします。

    シャード間クエリでは、待機時間、リソース消費量、複雑さが増します。 アプリケーションが複数のシャードからデータを取得する必要がある場合は、各シャードに対して同時に実行される並列ファンアウト クエリを使用し、結果を集計します。 並列処理の場合でも、最も遅いシャードによって全体的な待機時間が決まります。

    ヒント

    あるシャード内のエンティティが別のシャード内のエンティティを参照している場合は、2 番目のエンティティのシャード キーを最初のエンティティのスキーマの一部として含めます。 この方法では、シャード間で関連データを参照するクエリのパフォーマンスを向上させることができます。

  • ワークロードでシャード境界を越えて強力なトランザクション整合性が必要な場合は、シャード キーを再検討するか、シャーディングがニーズに合うかどうかを検討します。 シャード間トランザクションには課題があります。 2 フェーズ コミット、待機時間の追加、障害モードの導入、スループットの削減などの分散調整プロトコル。 ほとんどのシャード 化されたシステムでは、分散トランザクションが回避され、代わりに最終的な整合性が採用されます。 このモデルでは、各シャードが個別に更新され、アプリケーションは一時的な不整合を処理します。

  • 各シャード ストレージ ノードで使用可能なリソースが、データ サイズとスループットの観点からスケーラビリティ要件を処理できることを確認します。 詳細については、「 データのパーティション分割戦略」を参照してください。

  • すべてのシャードへの参照データのレプリケーションをご検討ください。 シャードに対するクエリで静的または低速のデータも参照する場合は、このデータをシャードに追加します。 その後、アプリケーションは、別のデータ ストアへのラウンド トリップを行わずに、クエリのすべてのデータをフェッチできます。

    複数のシャードに保持されている参照データが変更された場合、システムはすべてのシャードでこれらの変更を同期する必要があります。 この同期の実行中に、ある程度の不整合が発生する可能性があります。 この不整合を許容するようにアプリケーションを設計します。

  • シャード 化されたシステムは、運用上の負担を増やします。 以下の懸念事項に備えます。

    • 監視: システムの正常性の完全なビューを取得するには、すべてのシャードのメトリックとログを集計する必要があります。

    • バックアップと復元: シャード間の一貫性を維持するには、各シャードを個別にバックアップし、復元手順を設計する必要があります。 1 つのシャードをポイントインタイム リストアすると、他のシャードとの不整合が発生する可能性があります。

    • スキーマの変更: すべてのシャードでデータ定義言語 (DDL) の変更を調整する必要があります。

    これらのタスクは、スクリプトやその他の自動化ソリューションを使用して実装できます。

  • シャードを geolocate して、そのシャードを使用するアプリケーション インスタンスの近くにデータを配置できます。 この方法ではパフォーマンスを向上させることができますが、異なる場所の複数のシャードにアクセスする必要がある操作を追加で計画する必要があります。

このパターンを使用する場合

ヒント

カスタム シャーディング レイヤーを設計する前に、データ プラットフォームが既に処理するシャーディングの役割を決定します。 一部のサービスはシャーディングを完全に管理します。 たとえば、Azure Cosmos DB は、物理パーティション間でデータを分散し、分割を処理し、アプリケーションを関与させることなくクエリをルーティングします。 他のサービスはシャーディングを部分的に管理します。 たとえば、Azure SQL Database にはシャード マップ管理とデータ依存ルーティング用の エラスティック データベース ツール が用意されていますが、シャード キーを設計して分割操作を管理します。 シャーディング ロジックを自分でビルドして操作するときは、シャーディング パターンを使用します。

このパターンは次の状況で使用します。

  • データ ボリュームの合計が単一データベース インスタンスのストレージ容量を超えています。この不足に対処する垂直スケーリング オプションはありません。

  • トランザクションのスループットまたはクエリのコンカレンシーは、1 つのインスタンスで維持できる量を超えています。書き込み負荷も高いため、読み取りレプリカだけではボトルネックは解決されません。

    シャーディングにより、システムのパフォーマンスとスケーラビリティが向上し、可用性も向上します。 1 つのパーティションで障害が発生しても、アプリケーションが他のパーティションのデータにアクセスできなくなるとは限りません。 また、オペレーターは、すべてのデータを使用できないようにすることなく、1 つのパーティションのメンテナンスまたは復旧を実行できます。 詳細については、「 データのパーティション分割のガイダンス」を参照してください。

  • 規制またはコンプライアンスの要件では、特定のデータ サブセットが特定の地理的管轄区域に存在し、すべての要件を満たすことができる単一リージョンのデプロイがないことを義務付けています。

  • 個別のテナントまたは顧客セグメントでは、セキュリティ、パフォーマンス、または契約上の理由から、物理的なデータの分離が必要です。

    このようなシナリオでは、シャーディング パターンが従来のデータ ストアを超えて適用される場合があります。 たとえば、DNS ゾーン管理システムをチーム、環境、またはリージョンでシャード化して、DNS 変更の爆発半径を減らし、明確な所有権の境界を確立できます。 そのコンテキストでは、主な動機はスケーラビリティではなく、運用セグメント化です。 詳細については、「 プライベート DNS ゾーンのシャーディング」を参照してください。

シャーディングにより、データ アーキテクチャが大幅かつ永続的に複雑になります。 この複雑さは、システムの有効期間における開発、操作、テスト、クエリの設計、および障害復旧に影響します。

このパターンは、次の場合に適さない場合があります。

  • データ ボリュームとスループットは、予想される増加でも、1 つのデータベース インスタンス内に収まります。 垂直方向のスケーリングにより、クエリの簡略化とトランザクションの整合性が維持されます。

  • ボトルネックは読み取りボリュームであり、書き込みボリュームやストレージ容量ではありません。 読み取りレプリカとキャッシュ レイヤーは、シャーディングによって生じるクロスシャード クエリの複雑さなしで、読み取りトラフィックをオフロードできます。

  • データベース エンジンは、パフォーマンスのニーズを満たすテーブル レベルのパーティション分割をサポートしています。 1 つのインスタンス内でのパーティション分割には、複数のサーバーやルーティング ロジックは必要ありません。

  • 主要なクエリ パターンには、エンティティ間結合、マルチエンティティ トランザクション、または完全なデータセット集計が必要です。 シャーディングによってこれらの操作が高価になり、ファンアウト クエリと分散調整のオーバーヘッドがスケーリングの利点を上回る可能性があります。

ワークロード設計

ワークロードの設計でシャーディング パターンを使用して、 Azure Well-Architected Framework の柱で説明されている目標と原則に対処する方法を評価します。 次の表は、このパターンが各柱の目標をサポートする方法に関するガイダンスを示しています。

支柱 このパターンが柱の目標をサポートする方法
信頼性設計の決定は、故障に対するワークロードの回復性を高め、障害の発生後にワークロードを完全な機能状態に回復させるために役立ちます。 データと処理はシャードに分離されるため、1 つのシャードの誤動作はそのシャードに分離されたままです。

- データのパーティション分割
- RE:07 自己保護
コストの最適化では、ワークロードの投資収益率維持と向上に重点を置いています。 シャードを実装するシステムでは、多くの場合、コストの高い単一のリソースを使用するのではなく、よりコストの低いコンピューティング リソースやストレージ リソースの複数のインスタンスを使用することができます。 多くの場合、この構成によってコストを節約できます。

- CO:07 コンポーネントコスト
パフォーマンス効率 は、スケーリング、データ、およびコードの最適化を通じて、ワークロード の需要を効率的に満たすのに役立ちます。 スケーリング戦略でシャーディングを使用すると、データと処理は各シャードに分離されるため、要求は割り当てられたシャード内のリソースに対してのみ競合します。 シャーディングは、地理に基づいた最適化のためにも使用できます。

- PE:05 スケーリングとパーティショニング
- PE:08 データパフォーマンス

このパターンによって柱内にトレードオフが生じる場合は、他の柱の目標に照らして検討してください。

世界中で発行された書籍に関する広範な情報のコレクションを表示する Web サイトについて考えてみましょう。 このワークロードでカタログ化できる書籍の数と、一般的なクエリと使用パターンは、1 つのリレーショナル データベースで処理できる数を超えています。 ワークロード アーキテクトは、書籍の静的 ISBN をシャード キーとして使用して、複数のデータベース インスタンス間でデータをシャード化することを決定します。 具体的には、アーキテクトは ISBN の チェック ディジット (0 ~ 10) を使用します。これは、11 個の論理シャードに、かなりバランスの取れたデータ分散を提供します。

まず、アーキテクトは 11 個の論理シャードを 3 つの物理シャード データベースに併置します。 この 仮想パーティションアプローチでは、多くの論理パーティションが、より少ない物理ノードにマップされます。 アーキテクトは 、ルックアップ シャーディング アプローチを使用し、キーとサーバーのマッピングをシャード マップ データベースに格納します。

書籍カタログ アプリケーションのシャード化された SQL Database アーキテクチャを示す図。

Azure App Service には、書籍カタログ Web サイトというラベルが付けられます。 複数の SQL Database インスタンスと Azure AI Search インスタンスに接続します。 データベースの 1 つが ShardMap データベースとしてラベル付けされています。 これには、マッピング テーブルの一部を反映するテーブルの例が含まれています。これについては、この記事の後半で説明します。 このテーブルには、bookdbshard0、bookdbshard1、bookdbshard2 の 3 つのシャード データベース インスタンスが含まれています。 他のデータベースには、その下にあるテーブルの同じリスト例が含まれています。 テーブルには、Books、LibraryOfCongressCatalog、および他のテーブルのインジケーターが含まれます。 AI Search は、ファセット ナビゲーションとサイト検索に使用されます。 マネージド ID は App Service に関連付けられています。

ルックアップシャード マップ

シャード マップ データベースには、次のシャード マッピング テーブルとデータが含まれています。

SELECT ShardKey, DatabaseServer
FROM BookDataShardMap
| ShardKey | DatabaseServer |
|----------|----------------|
|        0 | bookdbshard0   |
|        1 | bookdbshard0   |
|        2 | bookdbshard0   |
|        3 | bookdbshard1   |
|        4 | bookdbshard1   |
|        5 | bookdbshard1   |
|        6 | bookdbshard2   |
|        7 | bookdbshard2   |
|        8 | bookdbshard2   |
|        9 | bookdbshard0   |
|       10 | bookdbshard1   |

Web サイト コードの例: シングル シャード アクセス

Web サイトは、存在する物理シャード データベースの数 (この場合は 3 つ) や、シャード キーをデータベース インスタンスにマップするロジックを認識していません。 書籍の ISBN のチェック ディジットがシャード キーであることを認識しているだけです。 Web サイトには、シャード マップ データベースへの読み取り専用アクセスと、すべてのシャード データベースへの読み取り/書き込みアクセス権があります。 この例では、Web サイトは Azure App Service ホストのシステム マネージド ID を承認に使用します。これにより、シークレットが接続文字列から除外されます。

Web サイトは、この例に示すように、 appsettings.json ファイル内または App Service アプリ設定を使用して、次の接続文字列で構成されます。

{
  ...
  "ConnectionStrings": {
    "ShardMapDb": "Data Source=tcp:<database-server-name>.database.windows.net,1433;Initial Catalog=ShardMap;Authentication=Active Directory Default;App=Book Site v1.5a",
    "BookDbFragment": "Data Source=tcp:SHARD.database.windows.net,1433;Initial Catalog=Books;Authentication=Active Directory Default;App=Book Site v1.5a"
  },
  ...
}

次のコードは、Web サイトがワークロードのデータベース シャード プールに対して更新クエリを実行する方法を示しています。

...

// All data for this book is stored in a shard based on the book's ISBN check digit,
// which is converted to an integer 0 - 10 (special value 'X' becomes 10).
int isbnCheckDigit = book.Isbn.CheckDigitAsInt;

// Establish a pooled connection to the database shard for this specific book.
using (SqlConnection sqlConn = await shardedDatabaseConnections.OpenShardConnectionForKeyAsync(key: isbnCheckDigit, cancellationToken))
{
  // Update the book's Library of Congress catalog information.
  SqlCommand cmd = sqlConn.CreateCommand();
  cmd.CommandText = @"UPDATE LibraryOfCongressCatalog
                         SET ControlNumber = @lccn,
                             ...
                             Classification = @lcc
                       WHERE BookID = @bookId";

  cmd.Parameters.AddWithValue("@lccn", book.LibraryOfCongress.Lccn);
  ...
  cmd.Parameters.AddWithValue("@lcc", book.LibraryOfCongress.Lcc);
  cmd.Parameters.AddWithValue("@bookId", book.Id);

  await cmd.ExecuteNonQueryAsync(cancellationToken);
}

...

前のコード例では、 book.Isbn978-8-1130-1024-6 の場合、 isbnCheckDigit6 である必要があります。 OpenShardConnectionForKeyAsync(6)呼び出しは、通常、キャッシュ アサイド アプローチを使用して実装されます。 シャード キー 6 のキャッシュされたシャード情報を使用できない場合、メソッドは、 ShardMapDb 接続文字列によって識別されたシャード マップ データベースに対してクエリを実行します。 このメソッドは、アプリケーション キャッシュまたはシャード データベースから bookdbshard2 の値を取得し、SHARD接続文字列のBookDbFragmentに置き換えます。 その後、このメソッドは、 bookdbshard2.database.windows.net へのプールされた接続を確立または再確立し、それを開き、呼び出し元のコードに返します。 その後、コードは、そのデータベース インスタンスの既存のレコードを更新します。

ウェブサイトのコード例: 複数のシャードアクセス

まれに、Web サイトで直接のクロスシャード クエリが必要な場合、アプリケーションはすべてのシャードで並列ファンアウト クエリを実行します。

...

// Retrieve all shard keys.
var shardKeys = shardedDatabaseConnections.GetAllShardKeys();

// Run the query in a fan-out style against each shard in the shard list.
Parallel.ForEachAsync(shardKeys, async (shardKey, cancellationToken) =>
{
  using (SqlConnection sqlConn = await shardedDatabaseConnections.OpenShardConnectionForKeyAsync(key: shardKey, cancellationToken))
  {
    SqlCommand cmd = sqlConn.CreateCommand();
    cmd.CommandText = @"SELECT ...
                          FROM ...
                         WHERE ...";

    SqlDataReader reader = await cmd.ExecuteReaderAsync(cancellationToken);

    while (await reader.ReadAsync(cancellationToken))
    {
      // Collect the results into a thread-safe data structure.
    }

    reader.Close();
  }
});

...

クロスシャード クエリの代わりに、このワークロードでは、サイト検索またはファセット ナビゲーションのために、Azure AI Search で外部管理インデックスを使用できます。

シャード インスタンスを追加する

ワークロード チームは、データ カタログまたはその同時使用量が大幅に増加した場合、3 つ以上のデータベース インスタンスが必要になる可能性があることを認識しています。 ワークロード チームは、データベース サーバーを動的に追加することは想定せず、新しいシャードがオンラインになったときにワークロードのダウンタイムを受け入れます。 新しいシャード インスタンスをオンラインにするには、既存のシャードから新しいシャードにデータを移動し、シャード マップ テーブルを更新する必要があります。 この非常に静的なアプローチでは、ワークロードは、シャード キー データベース マッピングを Web サイト コードに自信を持ってキャッシュできます。

この例のシャード キー ロジックには、11 個の物理シャードの上限があります。 ワークロード チームが、最終的に 11 個を超えるデータベース インスタンスが必要であると負荷見積もりを通じて判断した場合、シャード キー ロジックに侵入的な変更を加える必要があります。 この変更には、コードの変更と新しいキー ロジックへのデータ移行の慎重な計画が含まれます。

SDK の機能

SQL Database インスタンスへのシャード管理とクエリ ルーティング用のカスタム コードを記述する代わりに、 エラスティック データベース クライアント ライブラリを評価します。 このライブラリは、C# と Java の両方でシャード マップ管理、データ依存クエリ ルーティング、およびクロスシャード クエリをサポートします。

次のステップ

  • Azure Cosmos DB の整合性レベル: シャード間でデータを分散すると、整合性のトレードオフが生まれます。 この記事では、厳密から最終的まで、一貫性モデルの範囲と、可用性と待機時間への影響について説明します。
  • 水平、垂直、機能のデータのパーティション分割: この記事では、スケーラビリティの向上、競合の削減、パフォーマンスの最適化を行うために、クラウド内のデータをパーティション分割するためのその他の戦略について説明します。
  • インデックス テーブル パターン: シャード キーの設計だけでは、すべてのクエリをサポートできない場合があります。 アプリケーションでは、インデックス テーブル パターンを使用して、シャード キー以外のキーを指定することで、大きなデータ ストアからデータを取得できます。
  • 具体化されたビュー パターン: 一部のクエリ操作のパフォーマンスを維持するために、特にそのデータをシャード間で分散する場合に、データを集計して集計する具体化されたビューを作成できます。