2012-03-16 9 views
157

私は、私たちのページ(ソーシャルゲームタイプ)用のFacebookスタイルの通知システムを構築し始めています。私は今、そのようなシステムを設計する最良の方法を研究しています。私は、通知をユーザーやそのようなものにプッシュする方法は興味がありません。私はサーバー上でシステムを構築する方法を研究しています(通知の保存方法、保存場所、取得方法など)。通知システムの構築

そう...私たちは持っているいくつかの要件:ピーク時に

  • たちはおよそ1Kログインユーザ同時(と、より多くのゲストを持っているが、彼らは持っていないとして、彼らはここでは関係ありません。多くのイベントを生成する)
  • さまざまな種類の通知があります(ユーザーAはあなたを友達として追加しました、ユーザーBはあなたのプロフィールにコメントしました、ユーザーCは画像を好みました、ユーザーDはゲームXであなたを倒しました、...)
  • ほとんどのイベントは、1人のユーザー(ユーザーXはあなたのイメージが好きでした)に対して1つの通知を生成しますが、多くの通知が生成されます(ユーザーYの誕生日など)
  • 通知はグループ化する必要があります。いくつかの画像のようなインスタンスのための4つの異なるユーザならば、その画像の所有者は、4人のユーザがOKので、私が考えていたもの(FBがするよう)

をイメージしていない4つの別々の通知を気に入っていることを示す1つの通知を取得する必要がありますイベントが発生したときにイベントを保存するキューを作成する必要があるということです。その後、そのキューを見て、それらのイベントに基づいて通知を生成するバックグラウンドジョブ(gearman?)を持っています。このジョブは、各ユーザーのデータベースに通知を格納します(イベントが10人のユーザーに影響を与える場合は、10の別個の通知があります)。その後、ユーザーが通知のリストを持つページを開くと、私は彼のためのすべての通知を読んで(これを100個の最新の通知に限定しようと思っている)、それらをグループ化して最後に表示します。私はこのアプローチには心配です

もの:

  • :)地獄のような複雑でここに最適なストレージ・データベースです(私たちはMySQLを使用している)、または私は何か他のものを使用する必要があります(Redisのはのように思えます良いフィット感もあります)
  • 通知として何を保存すればよいですか?ユーザーID、イベントを開始したユーザーID、イベントの種類(それらをグループ化して適切なテキストを表示できるようにします)が表示されますが、通知の実際のデータを格納する方法はわかりません(例:URL &好きだった画像)。私は通知を生成するときにその情報を単に焼くべきですか、または影響を受けるレコード(イメージ、プロファイル、...)のIDを格納し、通知を表示するときにDBから情報を取り出す必要があります。
  • 通知ページを表示するときに100個の通知をオンザフライで処理する必要がある場合でも、パフォーマンスはここでOKです。
  • 可能性のある問題はすべてのリクエストで発生する可能性があります。 (私は通知をまとめてグループ化するので、それ自体で問題になる可能性があります)。これは避けられるかもしれませんが、私が(グループ化されている)通知のビューをオンザフライではなくバックグラウンドで生成した場合は避けてください。

私の提案する解決策と懸念事項についてどう思いますか?私がここで関連する何かを言及すべきだと思うなら、コメントしてください。

私たちは私たちのページにPHPを使用していますが、これは大きな要因ではありません。

+0

どのくらいの時間、それは一人の人間の努力として、この通知システムを構築することができました。私はちょうどそれに応じてタイムラインを作るための推定をしたい。 – Shaharyar

+0

@Shaharyar私はそれが通知システムの複雑さに依存すると思います。 – tyan

+0

私はMySQLと同じシステムを使って、優先度ベースの通知システムを構築しました。良いことは、それがそれ以上になると、数千人のユーザーに拡大するということです。特にAndroidとGCMで爆発します。私はredis、rabbitMQ、自然にメッセージキューを出すKafka、機能性のようなMySQLの代替案を知りたいです。 –

答えて

154

通知は、誰か(俳優)によって変更(動詞=追加、要求..)され、ユーザー(件名)に報告されるものに関するものです。以下は正規化されたデータ構造です(MongoDBを使用していますが)。特定のユーザーに変更について通知する必要があります。つまり、ユーザーごとの通知です。つまり、100人のユーザーが参加している場合、100個の通知が生成されます。

╔═════════════╗  ╔═══════════════════╗  ╔════════════════════╗ 
║notification ║  ║notification_object║  ║notification_change ║ 
╟─────────────╢  ╟───────────────────╢  ╟────────────────────╢ 
║ID   ║—1:n—→║ID     ║—1:n—→║ID     ║ 
║userID  ║  ║notificationID  ║  ║notificationObjectID║ 
╚═════════════╝  ║object    ║  ║verb    ║ 
        ╚═══════════════════╝  ║actor    ║ 
               ╚════════════════════╝ 

(あなたが合う時間フィールドを追加します)

あなたは「あなたは3つの友達リクエストを持っている」と言うことができるように、これは、オブジェクトごとに変更をグループ化するため、基本的です。そして、俳優ごとのグループ分けは便利なので、「ユーザーJames Bondはあなたのベッドに変更を加えました」と言うことができます。これはまた、あなたが好きなように通知を翻訳し、数える能力を与えます。

しかし、objectは単なるIDなので、オブジェクトが実際に変更され、その履歴を表示しない限り、別々の呼び出しで必要なオブジェクトに関する追加情報をすべて取得する必要があります(たとえば、 to ... ")

通知はサイトのユーザーにとってリアルタイムに近いため、変更が追加されると、nodejs + websocketsクライアントと結び付けられ、phpがすべてのリスナーのnodejsに更新をプッシュします。

+0

+1 @Artjom、これは素晴らしい投稿です。私は疑問に思っていた、あなたは 'オブジェクト'が単なるIDであることを言及します。どのような種類のオブジェクトがどのように分かっていますか?たとえば、友人のリクエストなどである可能性があります。通知を適切なイベントにリンクするにはどうすればよいですか?多くのおかげ – Mick

+1

notification_object.objectは、文字列「友情」のように、変更の種類を識別し 私はについて話その余分なデータと変更されたオブジェクトへの実際の参照は、notification_change.notificationObjectID –

+0

私が見ていることは非常にスマートです。だから、データベースの任意の場所にオブジェクトのクラスを格納する必要がありますか?あるいは 'notification_object.object'に格納された文字列からクラスを取得する方法がありますか?通知オブジェクトに関する情報を取得したい場合は、クラスとその識別子を使用して通知オブジェクトをロードする必要があるからです。私は正しい?あなたはこれのためのトリックを持っていますか?イベントリスナーのように、あるいは 'notification_object.object'とその識別子を実際のオブジェクトに変換するもの?多くのおかげ@Artjomが、これは大きな助けです:) – Mick

21

これは実際には抽象的な質問ですので、私たちはあなたが何をするべきかどうかを指摘する代わりに、議論しなければならないと思います。

は、ここで私はあなたの懸念について考えるものです:

  • はい、通知システムがなく、地獄のようにかかわらず、複雑です。このようなシステムのモデリングと実装には、さまざまなアプローチがありますが、中規模から高レベルの複雑さを持つことができます。

  • 私はいつも、データベース駆動型のものを作ろうとします。どうして?何が起こっているのかを完全に制御できることを保証することができますが、それは私だけです。データベース主導型のアプローチなしでコントロールすることができます。私を信じて、あなたはその事件をコントロールしたいです。

  • 実際のケースを例示してみましょう。どこからでも始めることができます。昨年、私はある種類のソーシャルネットワーク(もちろんFacebookのようなものではない)で通知システムをモデル化し実装しました。そこに通知を保存する方法は?私はnotificationsテーブルを持っていました。ここでは、target_user_id(明らかなものではありませんか?)、notification_type_id(通知タイプを持つ別のテーブルを参照しています)のgenerator_user_id )、テーブルを埋めるために必要なすべてのもの(タイムスタンプ、フラグなど)。私のnotification_typesテーブルはnotification_templatesテーブルとの関係を持っていましたが、通知の種類ごとに固有のテンプレートが格納されていました。たとえば、私はPOST_REPLYタイプを持っていました。テンプレートの種類は{USER} HAS REPLIED ONE OF YOUR #POSTSです。そこから、私はちょうど{}を変数として扱い、#を参照リンクとして扱いました。

  • はい、パフォーマンス OKでなければならないはずです。通知を考えるときは、サーバーが頭からつま先まで押すことを考えます。あなたがAjaxリクエストなどでそれをやろうとしている場合は、パフォーマンスについて心配する必要があります。しかし、私はそれが二度目の懸念だと思う。

私が設計したモデルはもちろん、あなたが従うことができる唯一のものではなく、最高のものでもありません。私は自分の答えが、少なくとも正しい方向にあなたを追うことを願っています。

+0

他のデータストアで制御できないのはなぜですか? –

+0

さて、私はそれを言っていませんでした。私が言ったことは、データベース主導のアプローチでしかデータ制御を保証できないことです。それは私だけです。私はそれを言い換えるつもりです。 –

+0

@DanielRibeiro通知テンプレートのプレースホルダ({...})は、さまざまなタイプの通知用にデータベース内の異なるテーブルセットのプレースホルダのデータを置き換える必要があります。例えば。 1つのテンプレートは「{ユーザー}があなたの写真を好きになっています。」というテンプレート、もう1つのテンプレートは「あなたの{ページ名}に新しいテンプレートがあります」というテンプレートです。 Etc. {PageName}と{user}と他のプレースホルダは異なるデータベーステーブルからマップするので、プレースホルダの値を動的に取得するためのスキーマは何でしょうか。あなたは@Ashishシュクラで尋ねたとして、 –

7
╔════════════════════╗ 
║notification  ║ 
╟────────────────────╢ 
║Username   ║ 
║Object    ║ 
║verb    ║ 
║actor    ║ 
║isRead    ║ 
╚════════════════════╝ 

これは2つのコレクションではなく、良い答えです。あなたは

は、このスキーマに問題がある場合、私に教えてください

(... 4つの質問などを尋ね、友達リクエストの保留中のような3)新しいイベントを取得するには、ユーザー名、オブジェクトとisReadで問い合わせることができます。

+2

トップの答えは、どの手段を正規化されたデータ構造を使用テーブルに重複はありません。あなたの答えはそれをしますか? –

関連する問題