270

ソーシャル アクティビティ ストリームを実装する最良の方法はどれか、あなたの意見を聞きたいです (Facebook が最も有名な例です)。関連する問題/課題は次のとおりです。

  • さまざまな種類のアクティビティ (投稿、コメントなど)
  • さまざまな種類のオブジェクト (投稿、コメント、写真など)
  • さまざまな役割に関与する 1 ~ n 人のユーザー (「ユーザー x は、ユーザー Z の投稿に対するユーザー y のコメントに返信しました」)
  • 同じアクティビティ アイテムの異なるビュー (「あなたがコメントした..」vs.「あなたの友人 x コメントした」vs.「ユーザー x コメントした..」=>「コメント」アクティビティの 3 つの表現)

..さらに、特にFacebookが行っているように、いくつかのアクティビティアイテムを1つにまとめて高度なレベルに引き上げる場合(「ユーザーx、y、zがその写真にコメントしました」

そのようなシステム、データモデルなどを実装するための最も柔軟で効率的かつ強力なアプローチに関するパターン、論文などに関する考えや指針をいただければ幸いです。

ほとんどの問題はプラットフォームに依存しませんが、Ruby on Rails でそのようなシステムを実装する可能性があります。

4

13 に答える 13

145

私はそのようなシステムを作成し、このアプローチを取りました:

次の列を持つデータベース テーブル: id、userId、type、data、time。

  • userIdは、アクティビティを生成したユーザーです
  • typeはアクティビティのタイプです (つまり、ブログ投稿を書いた、写真を追加した、ユーザーの写真にコメントした)
  • dataは、必要なものを何でも入れることができるアクティビティのメタデータを含むシリアル化されたオブジェクトです

これにより、フィードで実行できる検索/ルックアップが、ユーザー、時間、アクティビティ タイプに制限されますが、Facebook タイプのアクティビティ フィードでは、これは実際には制限されません。また、テーブルの正しいインデックスを使用すると、ルックアップが高速になります。

この設計では、各タイプのイベントに必要なメタデータを決定する必要があります。たとえば、新しい写真のフィード アクティビティは次のようになります。

{id:1, userId:1, type:PHOTO, time:2008-10-15 12:00:00, data:{photoId:2089, photoName:A trip to the beach}}

写真の名前は、写真を含む他のテーブルに保存されていることが最も確実であり、そこから名前を取得できますが、メタデータ フィールドで名前を複製します。速度が必要な場合は、他のデータベース テーブルの結合。また、50 人の異なるユーザーからの異なるイベント (たとえば 200 件) を表示するには、速度が必要です。

次に、さまざまな種類のアクティビティ エントリをレンダリングするための基本的な FeedActivity クラスを拡張するクラスがあります。イベントのグループ化は、データベースの複雑さを避けるために、レンダリング コードにも組み込まれます。

于 2008-10-15T16:45:31.913 に答える
118

これは、Etsy.com がアクティビティ ストリームをどのように設計したかを概説する非常に優れたプレゼンテーションです。Rails固有ではありませんが、これはこのトピックで見つけた最良の例です。

http://www.slideshare.net/danmckinley/etsy-activity-feeds-architecture

于 2011-02-16T21:34:26.167 に答える
45

私たちはアプローチをオープンソース化しました: https://github.com/tschellenbach/Stream-Framework 現在、この問題を解決することを目的とした最大のオープンソース ライブラリです。

Stream Framework を構築した同じチームが、ホストされた API も提供しており、複雑な作業を処理してくれます。getstream.ioをご覧ください。Node、Python、Rails、および PHP で使用できるクライアントがあります。

さらに、この高スケーラビリティの投稿を見て、関連する設計上の決定事項のいくつかを説明しました: http://highscalability.com/blog/2013/10/28/design-decisions-for-scaling-your-high-traffic- feeds.html

このチュートリアルは、Redis を使用して Pinterest のフィードのようなシステムをセットアップするのに役立ちます。始めるのはとても簡単です。

フィードの設計についてさらに学ぶには、Feedly の元になった次の記事を読むことを強くお勧めします。

Stream Framework は Python ベースですが、Ruby アプリから使用するのはそれほど難しくありません。単純にサービスとして実行し、その前に小さな http API を貼り付けることができます。他の言語から Feedly にアクセスするための API を追加することを検討しています。現時点では、自分でロールする必要があります。

于 2013-10-30T13:13:55.363 に答える
19

イベント ストリームの最大の問題は、可視性とパフォーマンスです。表示されるイベントをその特定のユーザーにとって興味深いものだけに制限する必要があり、それらのイベントを整理して識別するのにかかる時間を管理できるようにする必要があります。私は小規模なソーシャル ネットワークを構築しました。小規模では、データベースに「イベント」テーブルを保持することは機能しますが、中程度の負荷がかかるとパフォーマンスの問題になることがわかりました。

メッセージとユーザーのストリームが大きい場合は、イベントがメッセージとして個々のプロファイルに送信されるメッセージング システムを使用するのがおそらく最善です。つまり、ユーザーのイベント ストリームを簡単にサブスクライブして以前のイベントを簡単に確認することはできませんが、特定のユーザーのためにストリームをレンダリングする必要がある場合、メッセージの小さなグループをレンダリングするだけです。

これは Twitter の最初の設計上の欠陥だと思います。イベントを取得してフィルター処理するためにデータベースにアクセスしていたという記事を読んだことを覚えています。これはすべてアーキテクチャーと関係があり、Rails とは何の関係もありませんでした。Rails は (残念ながら) 「Ruby はスケールしない」というミームを生み出しました。最近、開発者が Amazon のSimple Queue Serviceを、はるかに高いスケーリング機能を持つ Twitter のようなアプリケーションのメッセージング バックエンドとして使用しているプレゼンテーションを見ました。負荷が十分に高い場合は、システムの一部として SQS を検討する価値があるかもしれません。 .

于 2008-10-15T14:03:42.473 に答える
12

別のソフトウェアを使用する場合は、アクティビティ ストリームの問題を正確に解決する Graphity サーバーをお勧めします (neo4j グラフ データベースの上に構築)。

アルゴリズムはスタンドアロンの REST サーバーとして実装されているため、独自のサーバーをホストしてアクティビティ ストリームを配信できます: http://www.rene-pickhardt.de/graphity-server-for-social-activity-streams-released-gplv3 /

論文とベンチマークで、ニュース ストリームの取得は取得したい項目の量に線形にしか依存しないことを示しました。データの非正規化から得られる冗長性はありません。

http://www.rene-pickhardt.de/graphity-an-effective-graph-model-for-retriving-the-top-k-news-feeds-for-users-in-social-networks/

上記のリンクには、このアプローチのスクリーンキャストとベンチマークがあります (グラフィティが 1 秒あたり 10,000 を超えるストリームを取得できることを示しています)。

于 2012-11-01T05:11:22.877 に答える
10
//実際のイベントごとに1つのエントリ
イベント{
  ID、タイムスタンプ、タイプ、データ
}

//イベントごと、そのイベントを含むフィードごとに1つのエントリ
events_feeds {
  event_id、feed_id
}

イベントが作成されたら、それを表示するフィードを決定し、それらをevents_feedsに追加します。フィードを取得するには、events_feedsから選択し、イベントに参加し、タイムスタンプ順に並べます。次に、そのクエリの結果に対してフィルタリングと集計を実行できます。このモデルを使用すると、追加の作業なしで、作成後にイベントプロパティを変更できます。

于 2008-10-15T20:43:59.873 に答える
10

昨日、このようなシステムの実装を開始しました。

プロパティIdActorIdTypeIdDateObjectId、および追加のDetailsキーと値のペアのハッシュテーブルを持つStreamEventクラスを作成しました。これは、データベースではStreamEventテーブル ( IdActorIdTypeIdDateObjectId ) およびStreamEventDetailsテーブル ( StreamEventIdDetailKeyDetailValue ) によって表されます。

ActorId 、TypeId およびObjectIdにより、Subject-Verb-Object イベントをキャプチャ (および後で照会) できます。各アクションにより、複数の StreamEvent インスタンスが作成される場合があります。

次に、 StreamEvent の各タイプのイベント ( LoginEventPictureCommentEventなど) のサブクラスを作成しました。これらの各サブクラスには、PictureId 、 ThumbNail 、 CommenText など (イベントに必要なものは何でも) など、よりコンテキスト固有のプロパティがあり実際hashtable/StreamEventDetail テーブルにキーと値のペアとして格納されます。

これらのイベントをデータベースから取得するときは、( TypeIdに基づく) ファクトリ メソッドを使用して正しい StreamEvent クラスを作成します。

StreamEvent の各サブクラスには、渡されたStreamContextクラスに基づいてイベントを画面に出力する Render( context As StreamContext ) メソッドがあります。StreamContext クラスを使用すると、ビューのコンテキストに基づいてオプションを設定できます。たとえば Facebook を見ると、ホームページのニュース フィードには、各アクションに関与している全員のフルネーム (およびプロフィールへのリンク) がリストされていますが、友人のフィードを見ると、ファースト ネームしか表示されません (ただし、他の俳優のフル ネームは表示されます)。 .

集約フィード (Facebook ホーム) はまだ実装していませんが、「うーん、これは面白いと思うかもしれません」アルゴリズムに基づいて入力されるフィールドUserIdStreamEventIdを持つAggregateFeedテーブルを作成すると思います。

どんなコメントでも大歓迎です。

于 2008-12-09T11:08:06.860 に答える
8

Rails で実装することに決めた場合は、おそらく次のプラグインが役立つでしょう。

アクティビティストリーム: http://github.com/face/activity_streams/tree/master

少なくとも、データ モデルと、プッシュおよびプル アクティビティ用に提供される API の両方の観点から、実装を確認できます。

于 2008-12-03T10:59:03.997 に答える
6

私はheymanと同様のアプローチを取りました。つまり、特定のアクティビティストリームに表示されるすべてのデータを含む非正規化されたテーブルです。アクティビティが限られている小さなサイトでは問題なく機能します。

上記のように、サイトが成長するにつれてスケーラビリティの問題に直面する可能性があります。個人的には、今のところスケーリングの問題については心配していません。後で心配します。

Facebookは明らかにスケーリングの素晴らしい仕事をしてきたので、エンジニアリングブログを読むことをお勧めします。すばらしいコンテンツがたくさんあるからです-> http://www.facebook.com/notes.php?id=9445547199

私は、上記の非正規化されたテーブルよりも優れたソリューションを検討してきました。これを達成するために私が見つけたもう1つの方法は、特定のアクティビティストリームに含まれるすべてのコンテンツを1つの行に凝縮することです。XML、JSON、またはアプリケーションで読み取ることができるシリアル化された形式で保存できます。更新プロセスも簡単です。アクティビティが発生したら、新しいアクティビティをキューに入れ(おそらく、Amazon SQSなどを使用して)、キューを継続的にポーリングして次のアイテムを探します。そのアイテムを取得して解析し、その内容をデータベースに保存されている適切なフィードオブジェクトに配置します。

この方法の良い点は、一連のテーブルを取得するのではなく、特定のフィードが要求されたときに1つのデータベーステーブルを読み取るだけでよいことです。また、リストを更新するたびに最も古いアクティビティアイテムをポップオフできるため、アクティビティの有限リストを維持できます。

お役に立てれば!:)

于 2008-11-19T17:44:50.077 に答える
5

このようなアクティビティ ストリームに関する 2 つのレールキャストがあります。

これらのソリューションにはすべての要件が含まれているわけではありませんが、いくつかのアイデアが得られるはずです。

于 2013-04-18T15:54:27.237 に答える
3

Plurk のアプローチは興味深いと思います。タイムライン全体が、Google Finance の株価チャートによく似た形式で提供されます。

ソーシャル ネットワーキング ネットワークがどのように機能するかを確認するには、 Ningを調べる価値があるかもしれません。開発者ページは特に役に立ちます。

于 2008-10-14T18:15:23.793 に答える
2

数か月前にこれを解決しましたが、私の実装は基本的すぎると思います。
以下のモデルを作成しました。

HISTORY_TYPE

ID           - The id of the history type
NAME         - The name (type of the history)
DESCRIPTION  - A description

HISTORY_MESSAGES

ID
HISTORY_TYPE - A message of history belongs to a history type
MESSAGE      - The message to print, I put variables to be replaced by the actual values

HISTORY_ACTIVITY

ID
MESSAGE_ID    - The message ID to use
VALUES        - The data to use

MESSAGE_ID_1 => "User %{user} created a new entry"
ACTIVITY_ID_1 => MESSAGE_ID = 1, VALUES = {user: "Rodrigo"}
于 2009-11-18T02:50:48.373 に答える