MongoDB Search でマルチテナンシーを実装すると、アプリケーションの 1 つのインスタンスが複数のテナントにサービスを提供できます。このページでは、 テナント分離を維持しつつ安全に増やすするようにデータとMongoDB Search インデックスを構築するための、 MongoDB Search に特に適用される設計に関する推奨事項について説明します。
重要
このガイダンスでは、単一のVPC内にテナントを配置できることを前提としています。厳密なネットワーク分離が必要な場合は、テナントごとに個別のプロジェクトを維持する必要があります。
戦略の選択
分離ニーズ、スケーリング目的、書込み負荷要件に基づいて戦略を選択します。最も一般的な戦略は次のとおりです。
すべてのテナントに単一のコレクション(推奨)
すべてのテナント戦略に1 つのコレクションを適用することをお勧めします。このアーキテクチャでは、すべてのテナント データを単一のデータベース内の 1 つのコレクションに保存します。各ドキュメント内に tenant_idフィールドを含めることで、テナントを区別できます。このフィールドは、UUID やテナント名など、テナントの一意の識別子にすることができます。
この集中型アプローチには、以下の利点があります。
インデックスの数を減らします
すべてのテナント データは 1 つのコレクションに保存されるため、必要なインデックスは1 つだけで、すべてのテナントのドキュメントを提供します。クラスターリソースの制限に達しないようにします。例には、
tenant_idおよびその他の共有フィールドまたはテナント固有のフィールドを 1 つのインデックスに含めることができます。メンテナンス操作を簡素化
すべてのデータを保存するコレクションが1 つだけであるため、複数のコレクションを保持したり、複数のデータベースにまたがってリソースを増やす必要はありません。また、単一のデータベース内の 1 つのコレクションのみを対象とする必要がある場合は、バックアップ、シャーディング、およびレプリケーション操作も簡素化します。
クエリを効率的に処理します
$search.compound.filter句内で等価演算子を使用して、クエリにtenant_idフィールドをフィルターとして指定します。注意
クエリ結果には、一致するテナントのドキュメントのみが含まれるため、テナント間でのデータの流出を防ぎます。
共存するテナントが同様のアクセス パターンとリソースサイズを共有する場合、この戦略は Luceneインデックスフィールド数も低く維持します。
重要
すべてのテナントの書込み負荷が高い場合、すべてのテナントを単一のコレクションに共存させると、書込み競合が発生する可能性があります。そのシナリオでは、書き込み (write) 負荷をより基礎のリソース全体に分散できるように、最も書き込み (write) が最も多いテナントを個別のコレクションに分割することを検討してください。
独自のリソースページまたはインデックスの作成要件を持つ大規模なテナントがある場合は、 ビュー を使用します。
テナントを分離します。ビューを作成し、
$matchと$expr操作を使用してテナントのドキュメントのみをフィルタリングします。インデックスは個別に作成されます。ビューでMongoDB Searchインデックスを作成します。
そのため、他のテナントが使用する共有インデックスに影響を与えずに、大規模なテナントのインデックス定義をカスタマイズできます。他のすべてのテナントは 1 つのインデックスを使用できます。
インデックス数が高いと、ベース クラスターに大きな負荷が発生し、ワークロードが中断される可能性があります。単一クラスター上の検索インデックスのハード制限は 2,500 です。ただし、クラスターがサポートできるインデックスの数は、クラスター階層とワークロードによって異なります。
M10のような小さいクラスター階層では、インデックスがはるかに少ないため、パフォーマンスの低下やメモリ不足エラーが発生する可能性があります。少数のインデックスから開始し、 を増やすにつれてクラスターのリソース使用量を監視します。
現在、テナントごとに 1コレクション戦略を適用している場合は、多数のインデックスによるリソース競合によってレプリケーションラグの OOM エラーが増加するのを防ぐために、基本階層をスケールアップすることをお勧めします。また、すべてのテナント戦略に 1 つのコレクションに移行することも推奨しています。
高書き込み (write) テナントの処理
特定のテナントの書き込み (write) 負荷が大きい場合、 共有コレクションの競合が発生する可能性があります。I/O 負荷を分散するために、最もボリュームのあるテナントのみを個別のコレクションに移動することをお勧めします。
一意の要件の処理(ビュー)
テナントに一意なインデックスの作成が必要な場合、またはテナントが他のテナントよりも大幅に大きい場合は、 MongoDBビューを使用します。
テナントごとに 1 つのデータベース
テナントごとのデータベース設定では、各テナントに独自のデータベースが含まれます。この設定はテナント データを分離しますが、クラスター内のインデックスの数も乗じます。すべてのテナントをサポートする 2,500 を超えるデータベースがある場合、クラスターは 2,500-インデックス上限に達する可能性があります。
警告
インデックス数が高いと、ベース クラスターに大きな負荷が発生し、ワークロードが中断される可能性があります。単一クラスター上の検索インデックスのハード制限は 2,500 です。ただし、クラスターがサポートできるインデックスの数は、クラスター階層とワークロードによって異なります。M10 のような小さいクラスター階層では、インデックスがはるかに少ないため、パフォーマンスの低下やメモリ不足エラーが発生する可能性があります。少数のインデックスから開始し、 を増やすにつれてクラスターのリソース使用量を監視します。
テナントごとに 1 つのコレクション(非推奨)
コレクションごとのテナント戦略は、各テナントを 共有データベース内の独自のコレクションにマッピングします。コレクションごとにインデックスを維持するオーバーヘッドによって、次の原因が発生する可能性があります。
レプリケーションラグの増加
リソース競合による OOM エラー
基本階層の不安定
テナントが非常に予測可能で軽量なワークロードでない限り、 MongoDB Search ではこの戦略は推奨されません。現在この戦略を使用している場合は、すべてのテナントに対して 1 つのコレクション戦略に移行してください。
インデックス付きフィールドの管理
インデックス フィールドを管理する際には、以下の推奨事項を考慮してください。
マルチテナント アプリケーションでは、多くの場合、検索、ソート、ファセット、フィルター処理可能なカスタムテナントごとのフィールドが必要になります。typeSet を使用してパスのサブフィールドを動的にインデックスと、 MongoDB Search はインデックス完全な再構築なしで自動的に新しいフィールドを選択します。これらのフィールドを静的にインデックスの作成することは避けてください。再構築がトリガーされ、CPU 負荷が付与され、インデックスのディスク容量が最大 2x を消費します。
注意
多すぎるフィールドのリスク
個別のフィールドが 1000 を超えると、 Luceneインデックスのパフォーマンスが低下する可能性があります。MongoDB Searchインデックスの一意のフィールドの数は、 MongoDB Search メトリクスで監視できます。100 個以上のフィールドをサポートする必要がある場合は、次のことをお勧めします。
ビュー を使用してテナントのサブセットを個別のインデックスに分離し、単一の Luceneインデックスに存在するフィールドの個別数を 1000 未満にします。
1 つのテナントが追加できるフィールドの数を制限します。
属性パターンを使用してテナントごとに異なるキーを保存する場合は、次の操作を行うことをお勧めします。
ビューを使用して、ドキュメントの埋め込み配列をフラット化します。
ディスクに保存されているMongoDB Searchインデックスをビューで作成します。
ドキュメントの配列をフラット化しない場合は、embeddedDocuments 演算子クエリ($elemMatch と同様)を使用して属性をクエリする必要があります。これは、フラット化された構造をクエリするよりもパフォーマンスが低くなります。