ソーシャルネットワークにアクティビティストリームを実装する方法


140

私は自分のソーシャルネットワークを開発していますが、ユーザーのアクションのストリームの実装例をWeb上で見つけていません...たとえば、各ユーザーのアクションをフィルターする方法は?アクションイベントを保存する方法 アクションストリームとそのアクションにどのデータモデルとオブジェクトモデルを使用できますか?


9
幸運、これは私たち全員が知りたい終わりのない質問です。facebookはそれをどのように引き離すのですか?答えは非常に複雑であり、私たちはそれを行う最も効率的な方法を決して知らないかもしれません。良いアプローチを見つけた場合は、ここに投稿して他の人が閲覧できるようにしてください。ところで、これはSOで何度も議論されているので、検索するとヒントが表示されます
JasonDavis

1
ストリームフレームワークは最も広く使用されているソリューションです:github.com/tschellenbach/Stream-Frameworkこのパッケージのリストも参照してください:djangopackages.com/grids/g/activities
Thierry

1
パーソナライゼーションに関しては、分析と機械学習に基づいています。getstream.io/ personalization
Thierry

回答:


241

要約:約100万人のアクティブユーザーと1億5,000万件の保存されたアクティビティについて、私は単純にしています:

  • 固有のアクティビティを保存するためにリレーショナルデータベースを使用します(アクティビティごとに1レコード/「発生したこと」)レコードをできるだけコンパクトにします。アクティビティID別に、または時間の制約があるフレンドIDのセットを使用して、アクティビティのバッチをすばやく取得できるように構造化します。
  • アクティビティレコードが作成されるたびにアクティビティIDをRedisに公開し、アクティビティを見る必要のある友達/購読者であるすべてのユーザーの「アクティビティストリーム」リストにIDを追加します。

Redisにクエリを送信して任意のユーザーのアクティビティストリームを取得し、必要に応じてdbから関連データを取得します。ユーザーが時間をさかのぼって参照する必要がある場合は、時間を指定してデータベースのクエリにフォールバックします(これを提供した場合でも)。


約1500万のアクティビティを処理するために、私はプレーンな古いMySQLテーブルを使用します。

次のようになります。

id             
user_id       (int)
activity_type (tinyint)
source_id     (int)  
parent_id     (int)
parent_type   (tinyint)
time          (datetime but a smaller type like int would be better) 

activity_typeアクティビティのタイプsource_id、アクティビティが関連するレコードを教えてくれます。したがって、アクティビティタイプが「お気に入りの追加」を意味する場合、source_idがお気に入りのレコードのIDを参照していることがわかります。

parent_id/ parent_type私のアプリのために便利です-彼らは活動が関連するものを私に教えてください。本がお気に入りの場合、parent_id / parent_typeは、アクティビティが特定の主キー(id)を持つ本(タイプ)に関連していることを通知します

(user_id, time)はである活動に索引を付け、クエリを行いuser_id IN (...friends...) AND time > some-cutoff-pointます idを破棄し、別のクラスター化インデックスを選択することは良い考えかもしれません-私は実験していません。

かなり基本的なものですが、機能し、シンプルで、ニーズの変化に応じて簡単に操作できます。また、MySQLを使用していない場合は、インデックスごとに改善できる可能性があります。


最新のアクティビティにすばやくアクセスできるように、私はRedisを実験しています。Redisはすべてのデータをメモリに格納するため、すべてのアクティビティをそこに配置することはできませんが、サイトで頻繁にヒットする画面のほとんどに十分に格納できます。各ユーザーの最新の100など。Redisを併用すると、次のように機能する可能性があります。

  • MySQLアクティビティレコードを作成する
  • アクティビティを作成したユーザーの友達ごとに、RedisのアクティビティリストにIDをプッシュします。
  • 各リストを最後のXアイテムまでトリミング

Redisは高速で、1つの接続を介してコマンドをパイプライン処理する方法を提供します。そのため、アクティビティを1,000人の友人にプッシュするには数ミリ秒かかります。

私が話していることの詳細な説明については、RedisのTwitterの例を参照してください:http : //redis.io/topics/twitter-clone

2011年2月の更新現在、5,000万のアクティブなアクティビティがあり、何も変更していません。これと同様のことを行うことの1つの良い点は、コンパクトで小さな行を使用することです。私はより多くのアクティビティとそれらのアクティビティのより多くのクエリを含むいくつかの変更を加えることを計画しており、私は間違いなく物事を迅速に保つためにRedisを使用します。私は他の分野でRedisを使用していますが、これは特定の種類の問題に本当にうまく機能します。

2014年7月更新月間アクティブユーザー数は最大で約70万人です。過去数年間、私は各ユーザーの最新の1000個のアクティビティIDを格納するために(箇条書きで説明されているように)Redisを使用してきました。システムには通常約1億のアクティビティレコードがあり、それらはまだMySQLに保存されており、同じレイアウトです。これらのレコードを使用すると、Redisのメモリを節約でき、アクティビティデータのレコードとして機能します。ユーザーが時間をさかのぼって何かを見つける必要がある場合は、これらのレコードを使用します。

これは賢い、または特に興味深い解決策ではありませんでしたが、うまく機能しました。


2
Redisの場合は+1。v2は仮想メモリを使用するため、Redisに完全に依存することが可能になるはずです
stagas

16
アクティビティのソースが複数ある場合(追加、コメントなど)、このテーブルを実際のアクティビティとどのように結合しますか?複数の左結合を使用していますか(それぞれがアクティビティテーブルに対して)?
Ali Shakiba、2011年

1
@casey Echoing @JohnS '質問- JOINさまざまなactivity_typeテーブルでどのように実行しますか?それらは、パフォーマンス面で高価な結合ですか?
Rob Sobers、2011

1
"JOIN"に関するJohnSの質問に誰かが回答しました。誰かがそれが説明される可能性があるリンクを投稿できますか?私も似たようなことをしなければならないので、とても助かります。
Waseem、2015年

3
参加していません。一意ごとに1つのクエリ activity_typeで、必要な他のデータを取得します。
15年

21

これは、mysqlを使用したアクティビティストリームの私の実装です。3つのクラスがあります:Activity、ActivityFeed、Subscriber。

Activityはアクティビティエントリを表し、そのテーブルは次のようになります。

id
subject_id
object_id
type
verb
data
time

Subject_idアクションを実行するオブジェクトobject_idのID、アクションを受け取るオブジェクトのIDです。typeそしてverbアクション自体説明します(たとえば、ユーザーが記事にコメントを追加すると、それぞれ「コメント」と「作成」になります)、結合を回避するためにデータに追加データが含まれます(たとえば、サブジェクト名を含めることができます)姓、記事のタイトルとURL、コメント本文など)。

各アクティビティは1つ以上のActivityFeedに属し、次のようなテーブルで関連付けられています。

feed_name
activity_id

私のアプリケーションでは、ユーザーごとに1つのフィードとアイテム(通常はブログ記事)ごとに1つのフィードがありますが、それらは自由に設定できます。

サブスクライバーは通常、サイトのユーザーですが、オブジェクトモデル内の任意のオブジェクトにすることもできます(たとえば、記事は彼の作成者のfeed_actionにサブスクライブできます)。

すべてのサブスクライバーは1つ以上のActivityFeedに属し、上記と同様に、次の種類のリンクテーブルによって関連付けられています。

feed_name
subscriber_id
reason

reasonここのフィールドは、購読者がフィードを購読した理由を説明します。たとえば、ユーザーがブログ投稿をブックマークした場合、その理由は「ブックマーク」です。これは、ユーザーへの通知のアクションを後でフィルタリングするのに役立ちます。

サブスクライバーのアクティビティーを取得するために、3つのテーブルを単純に結合します。WHERE今のような状態のため、選択するアクティビティが少ないため、結合は高速time > some hoursです。アクティビティテーブルのデータフィールドのおかげで、他の結合を避けています。

reasonフィールドの詳細な説明。たとえば、ユーザーへの電子メール通知のアクションをフィルタリングし、ユーザーがブログ投稿をブックマークした場合(そのため、「ブックマーク」の理由で投稿フィードをサブスクライブした場合)、ユーザーが受け取ることを望まないそのアイテムに対するアクションに関する電子メール通知。ただし、彼が投稿にコメントした場合(したがって、「コメント」の理由で投稿フィードを購読している場合)、他のユーザーが同じ投稿にコメントを追加したときに通知を受けたいです。理由フィールドは、ユーザーの通知設定とともに、この識別(ActivityFilterクラスを介して実装した)に役立ちます。


Nicolo martiniアクティビティに返信コメントを追加して、その下に表示したかったのですが、あなたの構造でどのように可能ですか?別のテーブルを追加するか、同じ場合は同じものを使用する必要がありますか?
Basit

この実装のパフォーマンスはどうですか?大きなテーブルでのテストはありますか?
Joshua F. Rountree、2012年

16

よく知られている多くの人々によって開発されている活動ストリームの現在のフォーマットがあります。

http://activitystrea.ms/

基本的に、すべてのアクティビティには、アクター(アクティビティを実行する)、動詞(アクティビティのアクション)、オブジェクト(アクターが実行する)、およびターゲットがあります。

たとえば、マックスはアダムの壁へのリンクを投稿しました。

彼らのJSONの仕様は、執筆時点でバージョン1.0に達しています。これは、適用できるアクティビティのパターンを示しています。

これらのフォーマットは、BBC、Gnip、Googleバズゴワラ、IBM、MySpace、Opera、Socialcast、Superfeedr、TypePad、Windows Live、YIID、その他の多くですでに採用されています。


こんにちは@sntranこの投稿が何年も前だったことを知っていますが、アクティビティストリームについてもっと質問があります。あなたが助けることができる方法はありますか?
hiswendy

承知しました。あなたの質問は何ですか?
息子TRAN-グエン

私の質問は実際にここに投稿されています!リンク。アクティビティストリームの基本的な理解はあると思いますが、それを実装する方法が本当にわかりません(つまり、angularまたはnode.jsを使用するはずですか?)そして、そこから、実際にアクティビティストリームをどのように作成しますか着信API JSON?これらは基本的な質問ですが、オンラインで回答を見つけることができませんでした。手伝って頂ければ幸いです。ありがとうございました!
hiswendy

13

通知システムが大規模なWebサイトでどのように機能するかについての説明は、ソーシャルネットワーキングWebサイトが友達の更新をどのように計算するかというスタックオーバーフローの質問にあると思います。ジェレミーウォールの答えで。彼はMessage Qeueの使用を提案し、それを実装する2つのオープンソースソフトウェアを示しています。

  1. RabbitMQ
  2. Apache QPid

ソーシャルアクティビティストリームを実装する最良の方法は何ですか?の質問も参照してください


1

パフォーマンスと分散型のメッセージキューが絶対に必要です。しかし、それだけではありません。永続データとして何を保存し、一時データとして何を保存するかなどを決定する必要があります。

とにかく、あなたが高性能でスケーラブルなシステムを求めているなら、それは私の友人にとって本当に難しい仕事です。しかし、もちろん、寛大なエンジニアの中にはこれに関する経験を共有している人もいます。LinkedInは最近、メッセージキューシステムKafkaをオープンソースにしました。その前に、FacebookはすでにオープンソースコミュニティにScribeを提供していました。KafkaはScalaで作成されており、最初は実行に時間がかかりますが、いくつかの仮想サーバーでテストしました。本当に速いです。

http://blog.linkedin.com/2011/01/11/open-source-linkedin-kafka/

http://incubator.apache.org/kafka/index.html


0

独自にロールする代わりに、APIを介して使用されるサードパーティのサービスを探すことができます。Collabinate(http://www.collabinate.com)と呼ばれるものを開始しましたこれは、グラフデータベースバックエンドと、高度な並行性とパフォーマンスを備えた方法で大量のデータを処理するためのかなり高度なアルゴリズムを備えています。FacebookやTwitterにあるような幅広い機能はありませんが、アクティビティストリーム、ソーシャルフィード、またはマイクロブログ機能をアプリケーションに構築する必要があるほとんどのユースケースでは十分です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.