Ich bin am Anfang des Aufbaus eines Benachrichtigungssystems im Facebook-Stil für unsere Seite (Social-Gaming-Typ) und recherchiere jetzt, wie ein solches System am besten gestaltet werden kann. Ich bin nicht daran interessiert, wie ich Benachrichtigungen an den Benutzer oder ähnliches senden kann (vorerst sogar). Ich recherchiere, wie man das System auf dem Server erstellt (wie man Benachrichtigungen speichert, wo man sie speichert, wie man sie abruft usw.).
Also ... einige Anforderungen, die wir haben:
- In Spitzenzeiten haben wir ungefähr 1k gleichzeitig angemeldete Benutzer (und viele weitere Gäste, aber sie spielen hier keine Rolle, da sie keine Benachrichtigungen haben), die viele Ereignisse generieren
- Es wird verschiedene Arten von Benachrichtigungen geben (Benutzer A hat Sie als Freund hinzugefügt, Benutzer B hat Ihr Profil kommentiert, Benutzer C hat Ihr Bild gefallen, Benutzer D hat Sie in Spiel X geschlagen, ...)
- Die meisten Ereignisse generieren 1 Benachrichtigung für 1 Benutzer (Benutzer X hat Ihr Bild gefallen), aber es gibt Fälle, in denen ein Ereignis viele Benachrichtigungen generiert (z. B. der Geburtstag von Benutzer Y).
- Benachrichtigungen sollten zusammengefasst werden. Wenn zum Beispiel vier verschiedene Benutzer ein Bild mögen, sollte der Besitzer dieses Bildes eine Benachrichtigung erhalten, die besagt, dass vier Benutzern das Bild gefallen hat und nicht vier separate Benachrichtigungen (genau wie FB).
OK, ich dachte also, ich sollte eine Art Warteschlange erstellen, in der ich Ereignisse speichern würde, wenn sie eintreten. Dann hätte ich einen Hintergrundjob ( Gearman ?), Der sich diese Warteschlange ansieht und Benachrichtigungen basierend auf diesen Ereignissen generiert. Dieser Job speichert dann Benachrichtigungen in der Datenbank für jeden Benutzer (wenn also ein Ereignis 10 Benutzer betrifft, gibt es 10 separate Benachrichtigungen). Wenn der Benutzer dann eine Seite mit der Liste der Benachrichtigungen öffnet, liest ich alle diese Benachrichtigungen für ihn (wir denken daran, diese auf 100 neueste Benachrichtigungen zu beschränken) und gruppiert sie und zeigt sie schließlich an.
Dinge, die mir bei diesem Ansatz Sorgen machen:
- komplex wie die Hölle :)
- Ist die Datenbank hier der beste Speicher (wir verwenden MySQL) oder sollte ich etwas anderes verwenden (Redis scheint auch gut zu passen)?
- Was soll ich als Benachrichtigung speichern? Benutzer-ID, Benutzer-ID, die das Ereignis ausgelöst hat, Art des Ereignisses (damit ich sie gruppieren und den entsprechenden Text anzeigen kann), aber dann weiß ich nicht, wie die tatsächlichen Daten der Benachrichtigung gespeichert werden sollen (z. B. URL und Titel des Bildes, das wurde gemocht). Soll ich diese Informationen beim Generieren der Benachrichtigung nur "backen" oder die ID des betroffenen Datensatzes (Bild, Profil, ...) speichern und die Informationen beim Anzeigen der Benachrichtigung aus der Datenbank ziehen?
- Die Leistung sollte hier in Ordnung sein, auch wenn ich beim Anzeigen der Benachrichtigungsseite 100 Benachrichtigungen im laufenden Betrieb verarbeiten muss
- Mögliches Leistungsproblem bei jeder Anfrage, da ich dem Benutzer die Anzahl der ungelesenen Benachrichtigungen anzeigen müsste (was für sich genommen ein Problem sein könnte, da ich Benachrichtigungen zusammenfassen würde). Dies könnte jedoch vermieden werden, wenn ich die Ansicht von Benachrichtigungen (wo sie gruppiert sind) im Hintergrund und nicht im laufenden Betrieb generiere
Was halten Sie von meinem Lösungsvorschlag und meinen Bedenken? Bitte kommentieren Sie, wenn Sie der Meinung sind, dass ich noch etwas erwähnen sollte, das hier relevant wäre.
Oh, wir verwenden PHP für unsere Seite, aber das sollte hier kein großer Faktor sein, denke ich.
quelle
Antworten:
Bei einer Benachrichtigung handelt es sich um etwas (Objekt = Ereignis, Freundschaft ..), das von jemandem (Schauspieler) geändert (Verb = hinzugefügt, angefordert ..) und dem Benutzer (Betreff) gemeldet wird. Hier ist eine normalisierte Datenstruktur (obwohl ich MongoDB verwendet habe). Sie müssen bestimmte Benutzer über Änderungen informieren. Es handelt sich also um Benachrichtigungen pro Benutzer. Wenn also 100 Benutzer beteiligt sind, generieren Sie 100 Benachrichtigungen.
(Fügen Sie Zeitfelder hinzu, wo Sie es für richtig halten.)
Dies dient im Wesentlichen zum Gruppieren von Änderungen pro Objekt, sodass Sie sagen können, dass Sie 3 Freundschaftsanfragen haben. Eine Gruppierung pro Schauspieler ist nützlich, sodass Sie sagen können, dass "Benutzer James Bond Änderungen in Ihrem Bett vorgenommen hat". Dies gibt Ihnen auch die Möglichkeit, Benachrichtigungen nach Belieben zu übersetzen und zu zählen.
Da es sich bei dem Objekt jedoch nur um eine ID handelt, müssten Sie alle zusätzlichen Informationen zu dem gewünschten Objekt mit separaten Aufrufen abrufen, es sei denn, das Objekt ändert sich tatsächlich und Sie möchten diesen Verlauf anzeigen (z. B. "Benutzer hat den Titel des Ereignisses in ... geändert". ")
Da Benachrichtigungen für Benutzer auf der Site nahezu in Echtzeit erfolgen, würde ich sie mit dem Client nodejs + websockets verknüpfen, wobei PHP das Update für alle Listener auf nodejs überträgt, wenn Änderungen hinzugefügt werden.
quelle
is_notification_read
in dernotification
Tabelle haben und es entsprechend markieren, wenn es istunread
,read
oderdeleted
.Dies ist wirklich eine abstrakte Frage, also müssen wir sie wohl nur diskutieren, anstatt darauf hinzuweisen, was Sie tun oder nicht tun sollten.
Folgendes denke ich über Ihre Bedenken:
Ja, ein Benachrichtigungssystem ist komplex, aber nicht so höllisch. Sie können viele verschiedene Ansätze zur Modellierung und Implementierung solcher Systeme verfolgen, und diese können von mittlerer bis hoher Komplexität reichen.
Pesonally versuche ich immer, Sachen datenbankgesteuert zu machen. Warum? Weil ich garantieren kann, dass ich die volle Kontrolle über alles habe, was vor sich geht - aber das bin nur ich. Sie können die Kontrolle ohne einen datenbankgesteuerten Ansatz haben. Vertrau mir, du wirst die Kontrolle über diesen Fall haben wollen.
Lassen Sie mich einen realen Fall für Sie veranschaulichen, damit Sie irgendwo anfangen können. Im vergangenen Jahr habe ich ein Benachrichtigungssystem in einer Art sozialem Netzwerk modelliert und implementiert (natürlich nicht wie Facebook). Wie habe ich dort Benachrichtigungen gespeichert? Ich hatte eine
notifications
Tabelle, in der ich diegenerator_user_id
(die ID des Benutzers, der die Benachrichtigung generiert), dietarget_user_id
(irgendwie offensichtlich, nicht wahr?), Dienotification_type_id
(die auf eine andere Tabelle mit Benachrichtigungstypen verwies) und alle aufbewahrte das notwendige Zeug, mit dem wir unsere Tabellen füllen müssen (Zeitstempel, Flaggen usw.). Meinenotification_types
Tabelle hatte früher eine Beziehung zu einernotification_templates
Tabelle, in der bestimmte Vorlagen für jede Art von Benachrichtigung gespeichert waren. Zum Beispiel hatte ich einenPOST_REPLY
Typ, der eine Art Vorlage hatte{USER} HAS REPLIED ONE OF YOUR #POSTS
. Von dort habe ich gerade die behandelt{}
als Variable und#
als Referenzlink;Ja, die Leistung sollte und muss in Ordnung sein. Wenn Sie an Benachrichtigungen denken, denken Sie an Server, die von Kopf bis Fuß pushen. Entweder wenn Sie es mit Ajax-Anfragen machen oder was auch immer, müssen Sie sich um die Leistung sorgen. Aber ich denke, das ist ein zweites Mal.
Das Modell, das ich entworfen habe, ist natürlich nicht das einzige, dem Sie folgen können, auch nicht das beste. Ich hoffe, meine Antwort folgt Ihnen zumindest in die richtige Richtung.
quelle
Dies scheint eine gute Antwort zu sein, anstatt zwei Sammlungen zu haben. Sie können nach Benutzername, Objekt und isRead abfragen, um neue Ereignisse abzurufen (z. B. 3 ausstehende Freundschaftsanfragen, 4 gestellte Fragen usw.).
Lassen Sie mich wissen, wenn es ein Problem mit diesem Schema gibt.
quelle
Ich persönlich verstehe das Diagramm für die akzeptierte Antwort nicht sehr gut. Daher werde ich ein Datenbankdiagramm hinzufügen, das auf dem basiert, was ich aus der akzeptierten Antwort und anderen Seiten lernen kann.
Verbesserungen werden gut aufgenommen.
quelle