12

私は50万人のユーザーを持つWebサイトを持っています(SQL Server 2008で実行しています)。ここで、ユーザーとその友達のアクティビティ ストリームを含めたいと思います。SQL Server でいくつかのことをテストした後、RDMS はこの種の機能には適していないことが明らかになりました。遅いです(データを大幅に非正規化した場合でも)。そのため、他の NoSQL ソリューションを検討した結果、これには MongoDB を使用できることがわかりました。アクティビティ ストリームのactivitystrea.ms json 仕様に基づくデータ構造に従います。 したがって、私の質問は次のとおりです。MongoDB のアクティビティ ストリームに最適なスキーマ設計は何でしょうか (このように多くのユーザーを使用すると、書き込みが非常に重くなることがほぼ予測できます。したがって、MongoDB を選択しました。「書き込み」パフォーマンスが優れています。私は 3 種類の構造について考えました。これが理にかなっているのか、それとも他のスキーマ パターンを使用する必要があるのか​​教えてください。

1 - このパターンですべての友達/フォロワーと一緒に各アクティビティを保存します。

 

    {
     _id:'activ123',
     俳優:{
            id:person1
            }、
    動詞:「従う」,
    物体:{
            objecttype:'人',
            id:'person2'
            }、
    updateon:Date(),
    消費者:[
            person3、person4、person5、person6、...など
            ]

    }

2 - 2 番目のデザイン: コレクション名 - activity_stream_fanout

    {
    _id:'activ_fanout_123',
    personId:person3,
    活動:[
    {
     _id:'activ123',
     俳優:{
            id:person1
            }、
    動詞:「従う」,
    物体:{
            objecttype:'人',
            id:'person2'
            }、
    updateon:Date(),
    }

    ]、[
    //アクティビティ フィード 2
    ]

    }


3 - このアプローチでは、アクティビティ アイテムを 1 つのコレクションに格納し、コンシューマーを別のコレクションに格納します。アクティビティでは、次のようなドキュメントがある場合があります。

    { _id: "123",
      俳優: { 人物: "UserABC" },
      動詞:「従う」、
      オブジェクト: { 人物: "someone_else" },
      updatedOn: 日付(...)

    }

そして、フォロワーのために、次の「通知」ドキュメントを用意します。

    { activityId: "123", 消費者: "someguy", updatedOn: Date(...) }
    { activityId: "123", 消費者: "otherguy", updatedOn: Date(...) }
    { activityId: "123", 消費者: "secondguy", updatedOn: 日付(...) }

あなたの答えは大歓迎です。

4

2 に答える 2

20

私は次の構造で行きます:

  1. 発生したすべてのアクションに対して 1 つのコレクションを使用し、Actions

  2. 誰が誰をフォローするかについては、別のコレクションを使用します。Subscribers

  3. 3 番目のコレクションを使用しNewsfeedます。特定のユーザーのニュース フィードに対して、アイテムがコレクションからファンアウトされActionsます。

コレクションは、Newsfeednew を非同期的に処理するワーカー プロセスによって設定されますActions。したがって、ニュース フィードはリアルタイムで読み込まれません。リアルタイムが重要であるという点で、私は Geert-Jan に同意しません。ほとんどのユーザーは、ほとんどの(すべてではない) アプリケーションで 1 分も遅延を気にしないと思います (リアルタイムの場合は、まったく別のアーキテクチャを選択します)。

の数が非常に多い場合consumers、ファンアウトに時間がかかることがあります。一方、コンシューマーをオブジェクトに直接配置しても、フォロワー数が非常に多い場合は機能せず、多くのインデックス スペースを占有する非常に大きなオブジェクトが作成されます。

ただし、最も重要なのは、ファンアウト設計がはるかに柔軟で、関連性スコアリングやフィルタリングなどが可能であることです。最近、MongoDB を使用したニュース フィード スキーマ設計に関するブログ記事を書きました。そこで、その柔軟性の一部について詳しく説明しています。

柔軟性について言えば、その activitystrea.ms の仕様には注意が必要です。異なるプロバイダー間の相互運用の仕様としては理にかなっているように見えますが、さまざまなアプリケーションからのアクティビティを集約するつもりがない限り、データベースに詳細な情報をすべて保存することはしません。

于 2012-06-07T10:52:03.490 に答える
1

アクセスパターンを確認する必要があると思います: このデータに対してどのクエリを最も実行する可能性が高いかなど.

私にとって最速である必要があるユースケースは、特定のアクティビティを各「アクティビティ コンシューマ」の「壁」(fb 用語で) にプッシュし、アクティビティが入ってきたときにすぐに実行できるようにすることです。

この観点から(私はあまり考えていませんでした)、2. は特定のユーザーのアクティビティを処理する前にバッチ処理するように見えるので、1 を使用します。これにより、更新の「即時」の必要性が失敗した場合。さらに、このユースケースでは 1 よりも 3. の方が有利だとは思いません。

1のいくつかの機能強化?すべてのアクティビティに対してコンシューマーの配列を定義する柔軟性が本当に必要かどうかを自問してください。このきめの細かいスケールでこれを指定する必要は本当にありますか? 代わりに、「俳優」の「友人」への言及で十分ではないでしょうか? (コンシューマーが通常数百 (?) の範囲にある場合、コンシューマー配列が各アクティビティのメッセージ全体の大部分であることを私は見ているので、これは長期的には多くのスペースになります。

多少関連するメモ: これらのアクティビティ ストリームのリアルタイム通知を実装する方法によっては、Pusher - http://pusher.com/および同様のソリューションを検討する価値があるかもしれません。

h番目

于 2012-06-06T22:14:33.500 に答える