多くの場合、データはソリューションの最も重要な部分と見なされます。これは、データがお客様ご自身および顧客の重要なビジネス情報を表しているためです。 そのため、データを慎重に管理することが重要です。 マルチテナント システムのストレージやデータ コンポーネントを計画する場合、ご自身のテナントのデータを共有または分離するためのアプローチを決定する必要があります。
この記事では、マルチテナント システム内にデータを格納する方法を決定するときに、ソリューション アーキテクトにとって必須である主な考慮事項と要件に関するガイダンスを提供します。 また、ストレージおよびデータ サービスへのマルチテナント機能の一般的な適用パターンと、避けるべきアンチパターンをいくつか提案します。 最後に、具体的な状況に応じたガイダンスをいくつか紹介します。
主な考慮事項と要件
ストレージおよびデータ サービスに使用するアプローチは、Azure Well-Architected Framework の重要な要素を含め、さまざまな観点から検討することが重要です。
スケール
ご自身のデータが格納されているサービスを使用するときは、所有しているテナントの数と、格納するデータの量を考慮する必要があります。 テナント数が少なく (たとえば 5 つ以下)、各テナントに格納しているデータが少量の場合、スケーラビリティに優れたデータ ストレージ アプローチを計画したり、データ リソース管理を完全に自動化するアプローチを構築したりする作業は、多くの場合、無駄になります。 しかし、拡大に伴い、明確な戦略を持ってデータとストレージのリソースをスケーリングし、その管理を自動化するメリットは大きくなってきます。 50 以上のテナントがある場合や、その規模まで拡大することを計画している場合は、それを考慮しながら、データとストレージのアプローチを設計することが特に重要です。
どの程度までスケーリングする予定かを考え、その規模に合わせて、ご自身のデータ ストレージ アーキテクチャのアプローチを明確に計画します。
パフォーマンスの予測可能性
マルチテナント データとストレージ サービスは、特にうるさい隣人の問題の影響を受けやすいため、 お使いのテナントそれぞれが、相互のパフォーマンスに影響を与えている可能性があるかどうかを検討することが重要です。 たとえば、ご自身のテナントの中に、使用パターンのピークが一定期間にわたって重複しているものはありますか? すべての顧客が毎日同じ時間にソリューションを利用していますか? それとも、要求が均等に分散していますか? これらの要因が、設計に必要な分離レベル、プロビジョニングする必要があるリソースの量、リソースをテナント間で共有できる度合いに影響します。
Azure のリソースと要求のクォータを、この決定の一環として考慮することが重要です。 たとえば、1 つのストレージ アカウントをデプロイして、お使いのテナントすべてのデータを格納するとします。 1 秒あたりのストレージ操作が特定の回数を超えると、ご自身のアプリケーションの要求は、Azure Storage によって拒否され、ご自身のテナントすべてが影響を受けます。 これは、調整動作と呼ばれます。 調整された要求を監視することが重要です。 詳細については、「特定のサービスの再試行ガイダンス」を参照してください。
データの分離
マルチテナント データ サービスを含むソリューションを設計する場合、通常、さまざまなデータ分離オプションやレベルがあり、それぞれに独自の利点とトレードオフがあります。 たとえば、次のように入力します。
- Azure Cosmos DB を使用する場合は、テナントごとに個別のコンテナーをデプロイし、複数のテナント間でデータベースとアカウントを共有できます。 また、必要な分離レベルに応じて、テナントごとに異なるデータベースまたはアカウントをデプロイすることも検討してください。
- BLOB データに Azure Storage を使用する場合は、テナントごとに個別の BLOB コンテナーをデプロイしたり、個別のストレージ アカウントをデプロイしたりできます。
- Azure SQL を使用する場合は、共有データベース内で個別のテーブルを使用できます。また、テナントごとに個別のデータベースやサーバーをデプロイすることもできます。
- すべての Azure サービスにおいて、1 つの共有 Azure サブスクリプション内へのリソースのデプロイを検討することも、複数の Azure サブスクリプション (おそらくテナントごとに 1 つ) を使用することもできます。
すべての状況に対応する単一のソリューションはありません。 どのオプションを選択するかは、いくつかの要因とご自身のテナントの要件によって異なります。 たとえば、お使いのテナントが特定のコンプライアンスまたは規制基準を満たす必要がある場合は、より高いレベルの分離を適用しなければならない可能性があります。 同様に、商業的要件によって顧客のデータを物理的に分離することが求められることも、うるさい隣人の問題を避けるために分離が余儀なくされることもあります。 さらに、テナントが独自の暗号化キーを使用する必要がある場合、テナントに個別のバックアップと復元ポリシーがある場合、テナントのデータをさまざまな地理的な場所に格納する必要がある場合は、他のテナントからの分離や、同様のポリシーを持つテナントでのグループ化が必要になる可能性があります。
実装の複雑さ
ご自身の実装の複雑さについて検討することが重要です。 お使いのアーキテクチャは、要件を満たしながらも、可能な限りシンプルにしておくことをお勧めします。 規模の拡大に伴い複雑になるアーキテクチャや、開発や維持のためのリソースや専門知識を持たないアーキテクチャにコミットすることは避けてください。
同様に、ご自身のソリューションが多数のテナントに対応する必要がない場合や、パフォーマンスやデータの分離に関する懸念がない場合は、ご自身のソリューションをシンプルに保ち、不必要に複雑にしないようにすることをお勧めします。
マルチテナント データ ソリューションで特に懸念されるのは、サポートするカスタマイズのレベルです。 たとえば、お使いのデータ モデルをテナントによって拡張することはできますか? また、カスタム データ ルールを適用することは可能ですか? この要件を前もって設計するようにします。 個々のテナントについてフォークしたり、カスタム インフラストラクチャを提供したりすることは避けてください。 カスタマイズされたインフラストラクチャは、スケーリング、ソリューションのテスト、および更新プログラムのデプロイを阻害します。 代わりに、機能フラグやその他の形式のテナント構成の使用を検討してください。
管理と操作の複雑さ
ご自身のソリューションをどのように運用するか、また、ご自身のマルチテナント アプローチが運用やプロセスにどのような影響を与えるかを考えます。 たとえば、次のように入力します。
- 管理: 定期メンテナンス作業など、テナント間の管理操作について検討します。 複数のアカウント、サーバー、データベースを使用する場合、どのように各テナントの運用を開始し、監視しますか?
- 監視と測定: テナントを監視または測定する場合は、ご自身のソリューションがどのようにメトリックを報告するか、また、要求をトリガーしたテナントに簡単にリンクできるかどうかを考慮します。
- 報告: 分離されたテナント間のデータを報告するには、各データベース上で個別にクエリを実行して結果を集計するのではなく、各テナントが、集中型データ ウェアハウスにデータをパブリッシュしなければならない場合があります。
- スキーマの更新: スキーマを設定するデータベースを使用する場合は、スキーマの更新をご自身の資産全体にデプロイする方法を計画します。 特定のテナントのデータベース クエリに使用するスキーマのバージョンを、お使いのアプリケーションに認識させる方法を検討します。
- 要件: テナントの高可用性の要件 (稼働時間のサービス レベル アグリーメント (SLA) など) とディザスター リカバリーの要件 (回復時刻の目標 (RTO)、回復ポイントの目標 (RPO) など) について検討します。 テナントの期待値がそれぞれ異なる場合、各テナントの要件を満たすことができますか?
- 移行: テナントを別のサービスの種類、別のデプロイ、別のリージョンに移動する必要がある場合、どのようにテナントを移行しますか?
[コスト]
一般的に、お使いのデプロイ インフラストラクチャに対するテナントの密度が高いほど、そのインフラストラクチャのプロビジョニング コストは低くなります。 ただし、インフラストラクチャを共有すると、うるさい隣人の問題のような課題が発生する可能性が高くなるため、そのトレードオフを慎重に検討してください。
考慮すべきアプローチとパターン
Azure アーキテクチャ センターの設計パターンの中には、マルチテナント ストレージとデータ サービスに関連するものがいくつかあります。 1 つのパターンに一貫して従うこともできます。 パターンを組み合わせて検討するのも良いでしょう。 たとえば、ほとんどのテナントに対してマルチテナント データベースを使用できますが、支払いが多いテナントや、通常とは異なる要件を持つテナントについては、シングルテナント スタンプをデプロイできます。 同様に、スタンプ内でマルチテナント データベースやシャード化されたデータベースを使用していても、通常は、デプロイ スタンプを使用してスケーリングすることをお勧めします。
デプロイ スタンプ パターン
デプロイ スタンプ パターンを使用してマルチテナント ソリューションをサポートする方法の詳細については、概要に関する記事を参照してください。
共有マルチテナント データベースとファイル ストア
共有マルチテナント データベース、ストレージ アカウント、ファイル共有をデプロイし、ご自身のすべてのテナント間で共有することを検討するのもよいでしょう。
このアプローチは、インフラストラクチャに対するテナントの密度が最も高いため、どのアプローチよりも低コストになる傾向があります。 また、管理、バックアップ、セキュリティ確保のためのデータベースやリソースが 1 つなので、管理オーバーヘッドが軽減されることもよくあります。
ただし、共有インフラストラクチャを使用する場合、注意が必要な点がいくつかあります。
- スケールの制限: 1 つのリソースに依存する場合は、そのリソースがサポートしているスケールと制限を考慮します。 たとえば、アーキテクチャが 1 つのデータベースに依存していると、最終的には単一データベースまたはファイル ストアの最大サイズ、あるいは最大スループット制限がハード ブロックになります。 このパターンを選択する前に、達成する必要がある最大スケールを慎重に検討し、それを、現在および将来の制限と比較してみてください。
- うるさい隣人: 特に、非常に負荷の高いテナント、あるいは他と比べて高いワークロードを生成しているテナントがある場合は、うるさい隣人の問題が要因になる可能性があります。 これらの影響を軽減するには、調整パターンまたはレート制限パターンを適用することを検討します。
- 各テナントの監視: シングル テナントの場合、アクティビティの監視と使用量の測定が困難な場合があります。 Azure Cosmos DB のように、リソース使用量に関するレポートを要求ごとに提供しているサービスがあり、この情報を追跡すれば、各テナントの消費量を測定できますが、 一方で、同じレベルの詳細情報を提供していないサービスもあります。 たとえば、ファイル容量の Azure Files メトリックは、Premium 共有を使用している場合にのみ、ファイル共有ディメンションごとに使用できます。 しかし、Standard レベルの場合、メトリックはストレージ アカウント レベルでのみ提供されます。
- テナントの要件: テナントには、セキュリティ、バックアップ、可用性、ストレージの場所など、さまざまな要件がある場合があります。 これらがシングル リソースの構成と一致しない場合は、対応できない可能性があります。
- スキーマのカスタマイズ: リレーショナル データベースを使用している場合、あるいはデータのスキーマが重要な状況では、テナントレベルでのスキーマのカスタマイズは困難です。
シャーディング パターン
シャーディング パターンでは、"シャード" と呼ばれる複数の個別のデータベースのデプロイが行われ、それぞれに 1 つ以上のテナントのデータが格納されています。 デプロイ スタンプとは異なり、シャードは、インフラストラクチャ全体が重複していることを意味するものではありません。 ご自身のソリューション内で他のインフラストラクチャを複製またはシャード化せずに、データベースをシャード化できます。
シャーディングは、"パーティション分割" と密接に関連しており、その用語は、よく同じ意味で使用されます。 データの水平的、垂直的、および機能的パーティション分割に関するガイダンスをご覧ください。
シャーディング パターンは、多数のテナントに合わせてスケーリングできます。 さらに、ワークロードによっては、シャードに対するテナントの密度を高くできる場合があるため、コスト面でも魅力的です。 また、シャーディング パターンを使用して、Azure サブスクリプションとサービスのクォータ、制限、制約に対応することもできます。
Azure Cosmos DB のように、シャーディングまたはパーティション分割のネイティブ サポートを提供しているデータ ストアもあります。 Azure SQL などの他のソリューションを使用している場合、特定のテナントについては、シャーディング インフラストラクチャを構築し、要求を正しいシャードにルーティングする方が複雑になる可能性があります。
また、シャーディングでは、テナント レベルの構成の違いをサポートし、顧客が独自の暗号化キーを提供することも困難です。
テナントごとに専用データベースを持つマルチテナントアプリ
シングル マルチテナント アプリケーションと、テナントごとに専用データベースをデプロイするアプローチも一般的です。
このモデルでは、各テナントのデータが他のテナントから分離され、テナントごとにある程度のカスタマイズをサポートできます。
テナントごとに専用のデータ リソースをプロビジョニングするため、このアプローチのコストは、共有ホスティング モデルよりも高くなる可能性があります。 ただし、Azure には、個々のデータ リソースのホスティング コストを、複数のテナントで共有するためオプションがいくつか用意されており、これらを考慮できます。 たとえば、Azure SQL を使用する場合は、エラスティック プールを検討することができます。 Azure Cosmos DB では、データベースのスループットをプロビジョニングでき、スループットは、そのデータベース内のコンテナー間で共有されます。ただし、この方法は、各コンテナーに対して保証されたパフォーマンスを必要とする場合は適していません。
このアプローチでは、データ コンポーネントだけがテナントごとに個別にデプロイされるため、ご自身のソリューション内の他のコンポーネントについて高密度を実現し、それらのコンポーネントのコストを削減できる可能性があります。
テナントごとにデータベースをプロビジョニングする場合は、自動デプロイ アプローチを使用することが重要です。
Geode パターン
Geode パターンは、マルチテナント ソリューションなど、地理的に分散されたソリューション専用に設計され、 高負荷と高レベルの回復性に対応します。 Geode パターンを実装する場合、データ層は地理的リージョン間でデータをレプリケートできる必要があり、複数地域の書き込みをサポートする必要があります。
Azure Cosmos DB は、このパターンをサポートするためにマルチ リージョン書き込みを提供しています。Cassandra では、マルチリージョン クラスターがサポートされています。 他のデータ サービスについては、一般的には、大幅なカスタマイズを行わないと、このパターンに対応できません。
回避すべきアンチパターン
マルチテナント データ サービスを作成する場合は、スケーリングできない状況を回避することが重要です。
リレーショナル データベースの場合は、次のような状況です。
- テーブルベースの分離。 単一データベース内で作業する場合は、テナントごとに個別のテーブルを作成しないようにしてください。 このアプローチを使用すると、単一データベースでは、それほど多くのテナントをサポートできなくなり、データのクエリ、管理、更新がますます困難になります。 代わりに、テナント識別子列が含まれる単一のマルチテナントテーブル セットを使用することを検討してください。 また、上記のいずれかのパターンを使用して、テナントごとに個別のデータベースをデプロイすることもできます。
- 列レベルのテナントのカスタマイズ。 シングル テナントにのみ適用されるスキーマを更新しないでください。 たとえば、単一のマルチテナント データベースについては、 特定のテナントの要件を満たす目的で新しい列を追加することを避けてください。 これは、カスタマイズの数が少なければ問題ないかもしれませんが、考えなければならないカスタマイズが多いと、すぐに手に負えなくなります。 代わりに、データ モデルを変更して、専用テーブル内の各テナントのカスタム データを追跡することを検討してください。
- 手動でのスキーマの変更。 共有データベースが 1 つしかなくても、お使いのデータベース スキーマは、手動で更新しないようにします。 適用した更新プログラムは見失いやすく、さらに多くのデータベースにスケールアウトする必要がある場合に、適用すべき適切なスキーマを特定するのは困難です。 代わりに、ご自身のスキーマの変更をデプロイするための自動化されたパイプラインを構築し、それを一貫して使用します。 専用データベースまたはルックアップ テーブル内のテナントごとに使用されるスキーマ バージョンを追跡してください。
- バージョンの依存関係。 お使いのアプリケーションが、単一バージョンのデータベース スキーマに依存しないようにしてください。 スケーリングに伴い、テナントごとに異なるタイミングでスキーマの更新を適用する必要が出てくる場合があります。 代わりに、お使いのアプリケーション バージョンと、少なくとも 1 つのスキーマ バージョンとの下位互換性を確保します。破壊的なスキーマの更新は避けるようにしてください。
データベース
マルチテナント機能に役立つ機能がいくつかあります。 ただし、これらは必ずしもすべてのデータベース サービスで使用できるとは限りません。 ご自身のシナリオに使用するサービスを決定するときに、それが必要かどうかを検討してください。
- 行レベルのセキュリティ: 共有マルチテナント データベース内の特定のテナントのデータに対して、セキュリティ分離を提供できます。 この機能は、Azure SQL と Postgres Flex 内で使用できますが、MySQL や Azure Cosmos DB などの他のデータベース内では使用できません。
- テナントレベルの暗号化: データに独自の暗号化キーを提供するテナントをサポートするために、必要になる場合があります。 この機能は、Always Encrypted の一部として Azure SQL 内で使用できます。 Azure Cosmos DB はアカウント レベルでカスタマー マネージド キーを提供します。また、Always Encrypted もサポートしています。
- リソース プール: 複数のデータベースまたはコンテナー間でリソースとコストを共有する機能が用意されています。 この機能は、Azure SQL のエラスティック プールとマネージド インスタンス、および Azure Cosmos DB のデータベース スループット内で使用できます。ただし、各オプションには注意すべき制限があります。
- シャーディングとパーティション分割: 一部のサービス内で、ネイティブ サポートが他よりも強くなっています。 この機能は、論理的および物理的パーティション分割を使用して Azure Cosmos DB で使用できます。 Azure SQL はシャーディングをネイティブでサポートしていませんが、この種類のアーキテクチャをサポートするシャーディング ツールが用意されています。
さらに、リレーショナル データベースやその他のスキーマベースのデータベースを使用する場合、複数のデータベースを管理するときは、どこでスキーマのアップグレード プロセスをトリガーするかを検討します。 小規模なデータベースの場合は、デプロイ パイプラインを使用して、スキーマの変更をデプロイできます。 データベースの数が増加するのに伴い、アプリケーション層で特定のデータベースのスキーマ バージョンを検出し、アップグレード プロセスを開始する方が良くなる場合があります。
ファイルおよび BLOB ストレージ
ストレージ アカウント内のデータの分離に使用するアプローチを考えてください。 たとえば、テナントごとに個別のストレージ アカウントをデプロイしたり、ストレージ アカウントを共有したり、個別のコンテナーをデプロイしたりします。 共有 BLOB コンテナーを作成し、BLOB パスを使用してテナントごとにデータを分離することもできます。 Azure サブスクリプションの制限とクォータを考慮し、慎重に成長計画を立てることで、将来のニーズに対応できるように Azure リソースを確実にスケーリングできるようにします。
共有コンテナーを使用する場合は、テナントがお互いのデータにアクセスできないように、慎重に認証および承認の戦略を立てます。 Azure Storage リソースへのアクセスをクライアントに提供するとき、バレー キー パターンについて検討します。
コストの割り当て
共有データ サービスを使用するには、使用量を測定し、コストをテナントに割り当てる方法を検討します。 可能な限り、自分で計算するのではなく、組み込みのメトリックを使用するようにします。 ただし、共有インフラストラクチャでは、個々のテナントのテレメトリを分割するのが難しくなり、アプリケーション レベルのカスタム測定を検討する必要が生じることがあります。
一般的には、Azure Cosmos DB、Azure Blob Storage などのクラウドネイティブ サービスによって、特定のテナントの使用状況を追跡およびモデル化するための、より詳細なメトリックが提供されます。 たとえば、Azure Cosmos DB の場合は、消費されたスループットが要求および応答ごとに提供されます。
共同作成者
この記事は、Microsoft によって保守されています。 当初の寄稿者は以下のとおりです。
プリンシパル作成者:
- John Downs | プリンシパル ソフトウェア エンジニア
その他の共同作成者:
- Paul Burpo | FastTrack for Azure のプリンシパル カスタマー エンジニア
- Daniel Scott-Raynsford |パートナー テクノロジ ストラテジスト
- Arsen Vladimirskiy | FastTrack for Azure のプリンシパル カスタマー エンジニア
パブリックでない LinkedIn プロファイルを表示するには、LinkedIn にサインインします。
次の手順
マルチテナント機能と特定の Azure サービスの詳細については、以下を参照してください。