13

私は、MongoDB が提供する速度とスケーラビリティにより、MongoDB に特に適していると思われるプロジェクトを開始しています。

私が現在興味を持っているモジュールは、リアルタイム チャットに関するものです。従来の RDBMS でこれを行う場合、次のように分割します。

  • チャネル (チャネルには多くのユーザーがいます)
  • ユーザー (ユーザーは 1 つのチャネルを持っていますが、多くのメッセージを持っています)
  • メッセージ (メッセージにはユーザーがいます)

この使用例の目的として、通常は一度に 5 つのチャネルがアクティブになり、それぞれが 1 秒あたり最大 5 つのメッセージを処理すると想定したいと思います。

高速である必要がある特定のクエリ:

  • 新しいメッセージを取得します (ブックマーク、タイム スタンプ、またはインクリメント カウンターに基づいていますか?)
  • チャンネルにメッセージを投稿する
  • ユーザーがチャネルに投稿できることを確認する

MongoDB のドキュメント制限が 4MB であることを念頭に置いて、スキーマをどのように設計しますか? あなたはどのように見えますか?気をつけるべき落とし穴はありますか?

4

3 に答える 3

3

チャット プロジェクトにはRedis、NGINX、および PHP-FPM を使用しました。とてもエレガントではありませんが、うまくいきます。パズルにはいくつかのピースがあります。

  1. クライアント コマンドを受け取り、それらを 1 つの大規模な LIST に入れる非常に単純な PHP スクリプトがあります。また、すべてのルーム LIST とユーザーのプライベート LIST をチェックして、配信する必要があるメッセージがあるかどうかを確認します。これは、jQuery で記述されたクライアントによってポーリングされ、数秒ごとに実行されます。

  2. サーバー側を毎秒 20 回の無限ループで操作するコマンド ライン PHP スクリプトがあり、このリストをチェックしてからこれらのコマンドを処理します。スクリプトは、誰がどの部屋にいるか、およびスクリプト メモリ内の権限を処理します。この情報は Redis には保存されません。

  3. Redis には、各部屋の LIST と、プライベート キューとして動作する各ユーザーの LIST があります。また、ユーザーがいるルームごとに複数のカウンターがあります。ユーザー カウンターがルーム内の合計メッセージ数よりも少ない場合は、差額を取得してユーザーに送信します。

このソリューションのストレス テストを行うことはできませんでしたが、少なくとも私の基本的なベンチマークからは、1 秒あたり何千ものメッセージを処理できる可能性があります。これを Node.js などに移植してパフォーマンスを向上させる機会もあります。Redis も成熟しており、Pub/Subscribe コマンドのような興味深い機能がいくつかあります。これは興味深いかもしれませんが、サーバー側でのポーリングを削除する可能性があります。

私は Comet ベースのソリューションを調べましたが、それらの多くは複雑で、文書化が不十分であるか、まったく新しい言語 (Jetty->Java、APE->C など) を学習する必要がありました...コメットの問題です。そのため、私はポーリングにこだわっています。

MongoDB でも同様のことができると思います。部屋ごとのコレクション、ユーザーごとのコレクション、カウンターを維持するコレクション。これらのメッセージの行き先を管理するバックエンド デーモンまたはスクリプトを作成する必要があります。ドキュメントをソートし、古いメッセージを自動的に消去する MongoDB の「限定コレクション」を使用することもできますが、適切なカウンターを維持するには複雑になる可能性があります。

于 2010-05-30T00:07:23.933 に答える
3

メッセージング システムに mongo を使用する理由 静的ストアがどれほど高速であっても (そして mongo が非常に高速であっても)、mongo であろうと db であろうと、メッセージ キューを模倣するには、スケーラブルでも効率的でもないある種のポーリングを使用する必要があります。それほど激しいことをしているわけではありませんが、適切なツールを適切な仕事に使用してみませんか? RabbitActiveMQなどのメッセージング システムを使用します。

mongo を使用する必要がある場合 (たぶん、それをいじりたいだけで、このプロジェクトはそれを行う良い機会です?) ユーザー用のコレクションがあると思います (各ユーザーオブジェクトには、そのユーザーが使用するキューのリストがあります)。聞きます)。メッセージの場合、キューごとにコレクションを作成できますが、その場合、関心のあるキューごとにメッセージをポーリングする必要があります。mongoでは単一のコレクションに対して「in」クエリを実行するのは簡単なので、単一のコレクションをキューとして持つ方が良いでしょう。 .name リスト [a,b,c]".

また、コレクションを mongo capped コレクションとして設定することを検討することもできます。これは、コレクションを設定するときに、コレクションが X バイト数または X 数のアイテムのみを保持する必要があることを mongo に伝えることを意味します。アイテムの追加には、メッセージ キューにとって非常に理想的な先入れ先出しの動作があります。繰り返しますが、これは実際にはメッセージング システムではありません。

于 2010-05-29T21:19:47.740 に答える
1

1) ape-project.org

2) http://code.google.com/p/redis/

3)これらすべてを完了したら、データをmongodbにダンプしてログを記録し、一貫したデータ(ユーザー、チャネル)も保存できます

于 2010-06-14T00:42:14.197 に答える