[解決済み] ソーシャルネットワークにアクティビティストリームを実装する方法
質問
自分のソーシャルネットワークを開発しているのですが、ユーザーのアクションのストリームを実装する例をウェブで見つけられませんでした...。例えば、各ユーザーのアクションをどのようにフィルタリングするのか?アクションイベントはどのように保存するのですか?アクションのストリームとアクション自体には、どのデータモデルとオブジェクトモデルを使用することができますか?
どのように解決するのですか?
概要 : 約100万人のアクティブユーザーと1億5千万件のアクティビティに対して、私はシンプルな状態を保っています。
- ユニークなアクティビティを保存するためにリレーショナルデータベースを使用する(1アクティビティにつき1レコード/ "起こったこと")できるだけコンパクトなレコードを作成する。アクティビティIDや、時間的制約のある友人IDのセットを使って、アクティビティを一括して素早く取得できるような構造にする。
- アクティビティレコードが作成されるたびにアクティビティIDをRedisに発行し、アクティビティを見るべき友人/購読者であるすべてのユーザーのための"アクティビティストリーム"リストにIDを追加します。
Redisに問い合わせ、任意のユーザーのアクティビティストリームを取得し、必要に応じてデータベースから関連データを取得します。ユーザーが過去にさかのぼって閲覧する必要がある場合は、時間によるデータベースへの問い合わせにフォールバックします(もし、これを提供する場合)。
私は、約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はすべてのデータをインメモリで保存するので、すべてのアクティビティをそこに入れることはできませんが、サイト上でよくアクセスされる画面のほとんどを保存することは可能です。各ユーザーの直近の100件とか、そんな感じです。Redisを使うと、こんな感じでしょうか。
- MySQLのアクティビティレコードを作成する
- アクティビティを作成したユーザーの友人ごとに、Redisの彼らのアクティビティリストにIDをプッシュします。
- 各リストを最後の X アイテムにトリムする
Redisは高速で、1つの接続でコマンドをパイプライン化する方法を提供します。そのため、アクティビティを1000人の友人にプッシュするのに数ミリ秒かかります。
私が言っていることの詳細は、RedisのTwitterの例を参照してください。 http://redis.io/topics/twitter-clone
2011年2月更新 現在、5,000万件のアクティブなアクティビティがありますが、何も変えていません。このようなことをする良い点は、コンパクトで小さな行を使用できることです。今後、さらに多くのアクティビティと、それらのアクティビティに対するクエリを含むような変更を行う予定ですが、その際にはぜひRedisを使ってスピードアップを図りたいと思っています。私は他の分野でもRedisを使っていますが、ある種の問題には本当によく効くんです。
2014年7月更新 月間アクティブユーザー数が約70万人になりました。ここ数年は、各ユーザーの直近1000件のアクティビティIDを保存するために、(箇条書きで説明したように)Redisを使用しています。通常、システムには約1億件のアクティビティレコードがありますが、それらはMySQLに保存され、今も同じレイアウトのままです。これらのレコードにより、少ないRedisメモリで済むようになり、アクティビティデータの記録として機能し、ユーザーが何かを見つけるためにさらに過去にページをめくる必要がある場合に使用することができるのです。
これは賢い解決策でもなければ、特別に面白い解決策でもありませんが、私にはよく役立っています。
関連
-
[解決済み] シングルトン・パターンの欠点やデメリットは何ですか?[クローズド]
-
[解決済み] 静的クラスとシングルトンパターンの違い?
-
[解決済み] 文字列からストリームを生成するにはどうすればよいですか?
-
[解決済み] あるストリームの内容を別のストリームにコピーするにはどうすればよいですか?
-
[解決済み] ログアウトする。GETかPOSTか?
-
[解決済み】アンチパターンとは何ですか?
-
[解決済み】MVCにおけるビジネスロジック【終了しました
-
[解決済み] ブリッジパターンはどのようなときに使うのですか?Adapterパターンとどう違う?
-
[解決済み] クロスカットの懸念事項の例
-
[解決済み】C++でファクトリーメソッドパターンを正しく実装する方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】クラスの命名 - すべてを"<WhatEver>Manager "と呼ぶのを避けるには?[クローズド]
-
[解決済み】アンチパターンとは何ですか?
-
[解決済み】REST APIのログインパターン
-
[解決済み] KotlinでBuilderパターンを実装するには?
-
[解決済み] コード内のスイッチをなくす方法【非公開
-
[解決済み] ブリッジパターンはどのようなときに使うのですか?Adapterパターンとどう違う?
-
[解決済み] デザインパターンとアーキテクチャパターンの違いは何ですか?
-
[解決済み] ゲームにおけるリプレイの概念的な仕組みについて教えてください。
-
[解決済み] ServiceLocatorはアンチパターンか?
-
[解決済み] デザインパターン 抽象ファクトリーとファクトリーメソッド