web-dev-qa-db-ja.com

MongoDBを使用して、効率的でスケーラブルなマルチテナントデータレイヤーを作成する方法

私は次のProject Mangementアプリのアーキテクチャ(例として)に取り組んでおり、特にマルチテナンシーに関してMongoDBデータレイヤーを設計するための最良の方法を明確にすることを求めています。アプリには複数の「サブアプリ」(カレンダー、タスクリスト、メディア、チームなど)があり、それぞれがデータベース(集中型DBまたは独自のプロジェクトDB)のコレクションにマッピングされます。

DBサーバー==レプリカセット。

質問

  1. 1つの巨大な集中型データベースを使用してすべてのアプリケーションデータを保存する必要がありますか、それともシステムで作成されるプロジェクトごとに個別のデータベースを作成する必要がありますか?
  2. 個別のDB戦略を選択した場合、DBが「自然に」複数のサーバーに分散され、したがって「自然に」複数のサーバーに負荷が分散される場合、データレイヤーをシャーディングする必要がなくなりますか?アプリケーションには、任意のプロジェクトのデータにアクセスするサーバーを指示するロジックが含まれます。
  3. プロジェクトごとに個別のDBを使用すると、パフォーマンスが向上しますか(特定のドキュメントを見つけるために、Mongoは、個別のプロジェクトDBで最大で数千のドキュメントを検索するだけで済みますが、巨大な一元化されたDBで数百万になる可能性があります)。
  4. MongoDBデータベースの32Mの最小フットプリントを減らすことはまったく可能ですか?私は--smallfilesmanual のドキュメントを読みましたが、それでも実際に私の質問に答えることはできませんでした。これはハードミニマムですか?
  5. 特定のプロジェクトが大量のトラフィックを受け取り、「騒々しい隣人」になった場合、解決策は単に新しいDBサーバーを起動し、そのプロジェクトを新しいサーバーに移動することでしょうか?それとも、そのサーバーのパフォーマンスを向上させるために、騒々しい隣人を収容するDBサーバーをシャーディングするためのより良いアプローチでしょうか?
  6. 削除されたプロジェクトのスペースをクリーンアップすること、および/または特定のプロジェクトデータベースに格納されている実際のデータ量に近いフットプリントを最小化するために各DBを「シュリンクラップ」することに関して、「メンテナンス」の懸念はありますか?
  7. すべてのProject DBで「ロールアウト」する必要があるデータ「スキーマ」の将来の変更に関して、どのような懸念事項に注意する必要がありますか? Mongoが「スキーマレス」であることを考えると、特定のコレクションに新しい「フィールド」を追加したい場合、DBの更新をロールアウトする必要なく、アプリロジックで追加するだけであると想定するのは正しいですか。自分自身?
  8. 特定のDBサーバーの現在の「ステータス」に関する情報を取得するには、どのMongoDBの「ツール」を使用しますか?
  9. 注意すべき特定のDBサーバーに格納できるDBの数に制限はありますか?
  10. 個々のDB戦略はバックアップにどのように影響しますか?多くのDBサーバー間で多くのDBを(ディザスターリカバリーのためにS3に)バックアップするときに注意する必要がある懸念事項はありますか?

アプリスタック

Ubuntu 12.04 LTS
Nginx
node.js
express.js
MongoDB

現在の作業戦略

私の現在の作業戦略は、1つのデータベースを使用して、ユーザー、通知、メッセージ、使用状況、設定などの高レベルの「グローバル」データを格納することです。そして、システムで作成されたプロジェクトごとに新しいデータベースを作成します。

これは、多くの理由で理想的なアプローチのように思われます。セキュリティ(各DBには独自の資格がある)、壊滅的な回復(1つのDBサーバーがダウンしてもアプリ全体がダウンしないため)、およびパフォーマンス(Mongoは探しているドキュメントを見つけるためにはるかに少ないドキュメントを検索する場合)。

アプリケーションには、特定のDBサーバーで利用可能なスペースを自動的に検出し、次の利用可能なDBサーバーで新しいプロジェクトデータベースを作成するロジックが含まれます。

MongoHQが提供する この記事 によると、これは「最良の」戦略ですが、大量のストレージを消費します。特に、各DBは空の場合でも32Mを消費します。 Techcrunchを取得する「フリーミアム」アプリを提供している場合、MongoHQなどのサービスを使用すると非常に高価になります。

したがって、ProjectManagerがシステム上に3つのプロジェクトを持っているシナリオでは、データレイヤーは次のようになります。

ProjectManager
  Users
  Notifications
  Messages
  Usage
  Preferences

Project01
  Calendar
  Tasks
  Media
  Team

Project02
  Calendar
  Tasks
  Media
  Team

Project03
  Calendar
  Tasks
  Media
  Team

上記のProjectXX DBはそれぞれ非常に小さいものです。それぞれが最大で約2000〜3000のドキュメントを保存します。

洞察をお寄せいただきありがとうございます。

6
AJB

覚えておくべきいくつかのこと:

  • 大規模で効率的であるものは、小規模では必ずしも効率的ではありません。
  • 大規模に必要とするものを考える実際に実際に必要なものあなたがその規模に達したときに必要です。
  • 最高のパフォーマンスはアプリケーション固有であり、汎用ではありません。アプリのパフォーマンスが最も良いのは、私のアプリのパフォーマンスがそうでない場合があります。
  • スキーマレスのすべての手段は、DBシステムが変更しても、DBシステムがあなたと戦わないことです。アプリケーションコードには、設計しなければならないスキーマがまだあります。
    • 新しいフィールドを追加しますか? Mongoは関係ありません。app-logicだけが関係します。
    • フィールドを単一値から複数値に変更しますか?モンゴは気にしない。しかし、コード内の関数は間違いなくそうです。データ移行パスを作成するか、両方のケースを処理するようにコードを設計する必要があります。
  • サーバーの設置面積を拡大する必要がある場合は、運用上の制限(たとえば、どのAWSインスタンスに対応できるか)が影響します。

そのため、現在システムを構築する際に従うべき設計パターンがいくつかあります。これらは、学習の内容に応じて、後で簡単にスケーリングできる項目です。

今すぐシャード
これにより、良いシャードキーについて考えるようになります。シャードキーは、スキーマを変更するのが難しい非スキーマの一部であるためです。この時点では、パフォーマンスをシャーディングするのではなく、シャーディングして、コードが確実に処理できるようにし、いくつかのマイルストーンでパフォーマンスの問題を解決します。

現在、エンジニアのマルチデータベースサポート
複数のデータベース、または複数のMongoデータベースのクラスターが必要になると予想される場合は、初期段階でデータの局所性を構築すると、後でデータベースを配置しやすくなります。現在、すべてが1つのクラスターにあり、すべてのプロジェクト/タスク/カレンダー/ユーザーが同じ3つのMongoDインスタンスにある可能性がありますが、カレンダーデータベースがすべてを遅くしているため、SSDベースのインスタンスに移動する必要があることがわかった場合、それははるかに簡単に変更されます。

データベースの圧縮は一部のケースでのみ重要
2GBのデータベースファイルに200MBのデータベースが含まれているため、データベースファイル自体がmmmapされているため、ストレージサブシステムがランダムI/Oを適切に処理する限り、実際にパフォーマンスが低下することはありません。また、圧縮はしばらくの間ノードをオフラインにします。これにより、通常の操作に重大な影響を与える可能性があります。また、ドキュメントを削除しない場合でも、圧縮について心配する必要はありません。

分離したコレクションと分離したデータベースで何が得られるかを知る
同じデータベース内のコレクションは、同じデータベースロックを共有します。これは、MongoDBの各バージョンで着実に抑制されてきました。
同じインスタンス内のデータベースは相互にI/Oを共有し、ごくわずかなグローバルロックイベントがそこに残っています。

インデックスは非常に重要です
RAM=少なくともインデックスをメモリに保持するのに十分でない場合、パフォーマンスは本当に悪くなります。取得するサイズによっては、シャーディングまたはRAMに再び適合するインデックスを取得するためにコレクションを分割します。これはマルチテナントが問題になる可能性がある領域の1つです。1つの中にいくつかの大きな未使用のテナントがある場合システム全体を実行するには、これらすべてのインデックスのコレクションをRAMに保持する必要があります。テナントに基づいてコレクションを分割すると、未使用のインデックスをほとんどペナルティなしでページアウトできます。

6
sysadmin1138