1. ホーム
  2. design-patterns

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

2022-05-06 22:59:54

質問

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

どのように解決するのですか?

概要 : 約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メモリで済むようになり、アクティビティデータの記録として機能し、ユーザーが何かを見つけるためにさらに過去にページをめくる必要がある場合に使用することができるのです。

これは賢い解決策でもなければ、特別に面白い解決策でもありませんが、私にはよく役立っています。