Ich entwickle mein eigenes soziales Netzwerk und habe im Web keine Beispiele für die Implementierung des Streams der Benutzeraktionen gefunden. Wie kann ich beispielsweise Aktionen für jeden Benutzer filtern? Wie speichere ich die Aktionsereignisse? Welches Datenmodell und Objektmodell kann ich für den Aktionsstrom und für die Aktionen selbst verwenden?
design-patterns
architecture
stream
social-networking
Nicolò Martini
quelle
quelle
Antworten:
Zusammenfassung : Für ungefähr 1 Million aktive Benutzer und 150 Millionen gespeicherte Aktivitäten halte ich es einfach:
Fragen Sie Redis ab, um den Aktivitätsdatenstrom für einen beliebigen Benutzer abzurufen, und rufen Sie dann die zugehörigen Daten nach Bedarf aus der Datenbank ab. Versuchen Sie, die Datenbank nach Zeit abzufragen, wenn der Benutzer in der Zeit weit zurückblättern muss (wenn Sie dies überhaupt anbieten).
Ich verwende eine einfache alte MySQL-Tabelle für etwa 15 Millionen Aktivitäten.
Es sieht ungefähr so aus:
activity_type
sagt mir die Art der Aktivität,source_id
sagt mir den Datensatz, mit dem die Aktivität zusammenhängt. Wenn der Aktivitätstyp "Favorit hinzugefügt" bedeutet, weiß ich, dass sich die Quell-ID auf die ID eines Favoriten-Datensatzes bezieht.Die
parent_id
/parent_type
sind nützlich für meine App - sie sagen mir, worauf sich die Aktivität bezieht. Wenn ein Buch favorisiert wurde, würde parent_id / parent_type mir mitteilen, dass sich die Aktivität auf ein Buch (Typ) mit einem bestimmten Primärschlüssel (ID) bezieht.Ich indiziere
(user_id, time)
und frage nach Aktivitäten, die sinduser_id IN (...friends...) AND time > some-cutoff-point
. Es könnte eine gute Idee sein, die ID fallen zu lassen und einen anderen Clustered-Index auszuwählen - damit habe ich nicht experimentiert.Ziemlich einfaches Zeug, aber es funktioniert, es ist einfach und es ist einfach, damit zu arbeiten, wenn sich Ihre Bedürfnisse ändern. Wenn Sie MySQL nicht verwenden, können Sie möglicherweise indextechnisch bessere Ergebnisse erzielen.
Um schneller auf die neuesten Aktivitäten zugreifen zu können, habe ich mit Redis experimentiert . Redis speichert alle seine Daten im Speicher, sodass Sie nicht alle Ihre Aktivitäten dort ablegen können, aber Sie könnten genug für die meisten häufig verwendeten Bildschirme auf Ihrer Website speichern. Die letzten 100 für jeden Benutzer oder so ähnlich. Mit Redis in der Mischung könnte es so funktionieren:
Redis ist schnell und bietet eine Möglichkeit, Befehle über eine Verbindung zu leiten. Das Versenden einer Aktivität an 1000 Freunde dauert also Millisekunden.
Eine ausführlichere Erklärung dessen, worüber ich spreche, finden Sie im Twitter-Beispiel von Redis: http://redis.io/topics/twitter-clone
Update Februar 2011 Ich habe momentan 50 Millionen aktive Aktivitäten und nichts geändert. Eine schöne Sache bei etwas Ähnlichem ist, dass es kompakte, kleine Reihen verwendet. Ich plane einige Änderungen vorzunehmen, die viel mehr Aktivitäten und mehr Abfragen dieser Aktivitäten beinhalten würden, und ich werde Redis definitiv verwenden, um die Dinge schnell zu halten. Ich benutze Redis in anderen Bereichen und es funktioniert wirklich gut für bestimmte Arten von Problemen.
Update Juli 2014 Wir haben bis zu 700.000 aktive Benutzer pro Monat. In den letzten Jahren habe ich Redis (wie in der Liste mit Aufzählungszeichen beschrieben) zum Speichern der letzten 1000 Aktivitäts-IDs für jeden Benutzer verwendet. Es gibt normalerweise ungefähr 100 Millionen Aktivitätsdatensätze im System und sie werden immer noch in MySQL gespeichert und haben immer noch das gleiche Layout. Mit diesen Aufzeichnungen können wir mit weniger Redis-Speicher davonkommen, sie dienen als Aufzeichnung von Aktivitätsdaten und wir verwenden sie, wenn Benutzer in der Zeit weiter zurückblättern müssen, um etwas zu finden.
Dies war keine clevere oder besonders interessante Lösung, aber sie hat mir gute Dienste geleistet.
quelle
JOIN
an den verschiedenenactivity_type
Tischen durch? Sind diese Verbindungen in Bezug auf die Leistung teuer?activity_type
, um die anderen Daten abzurufen, die Sie benötigen.Dies ist meine Implementierung eines Aktivitätsstroms mit MySQL. Es gibt drei Klassen: Activity, ActivityFeed, Subscriber.
Aktivität stellt einen Aktivitätseintrag dar und seine Tabelle sieht folgendermaßen aus:
Subject_id
ist die ID des Objekts, das die Aktion ausführt,object_id
die ID des Objekts, das die Aktion empfängt.type
undverb
beschreibt die Aktion selbst (wenn ein Benutzer beispielsweise einen Kommentar zu einem Artikel hinzufügt, würde er "Kommentar" bzw. "Erstellt" sein), enthalten Daten zusätzliche Daten, um Verknüpfungen zu vermeiden (zum Beispiel kann sie den Betreffnamen enthalten und Nachname, Titel und URL des Artikels, Kommentarkörper usw.).Jede Aktivität gehört zu einem oder mehreren ActivityFeeds und wird durch eine Tabelle verknüpft, die folgendermaßen aussieht:
In meiner Anwendung habe ich einen Feed für jeden Benutzer und einen Feed für jeden Artikel (normalerweise Blog-Artikel), aber sie können beliebig sein.
Ein Abonnent ist normalerweise ein Benutzer Ihrer Site, es kann sich jedoch auch um ein beliebiges Objekt in Ihrem Objektmodell handeln (z. B. könnte ein Artikel die feed_action seines Erstellers abonniert haben).
Jeder Abonnent gehört zu einem oder mehreren ActivityFeeds und ist wie oben durch eine Verknüpfungstabelle dieser Art verbunden:
Das
reason
Feld hier erklärt, warum der Abonnent den Feed abonniert hat. Wenn ein Benutzer beispielsweise einen Blog-Beitrag mit einem Lesezeichen versehen kann, lautet der Grund "Lesezeichen". Dies hilft mir später beim Filtern von Aktionen für Benachrichtigungen an die Benutzer.Um die Aktivität für einen Abonnenten abzurufen, füge ich die drei Tabellen einfach zusammen. Der Beitritt ist schnell, da ich dank einer
WHERE
Bedingung, die wie jetzt aussieht , nur wenige Aktivitäten auswähletime > some hours
. Ich vermeide andere Verknüpfungen dank des Datenfelds in der Aktivitätstabelle.Weitere Erklärung vor
reason
Ort. Wenn ich beispielsweise Aktionen für E-Mail-Benachrichtigungen an den Benutzer filtern möchte und der Benutzer einen Blog-Beitrag mit einem Lesezeichen versehen hat (und daher den Beitrags-Feed mit dem Grund "Lesezeichen" abonniert), möchte ich nicht, dass der Benutzer ihn erhält E-Mail-Benachrichtigungen über Aktionen für dieses Element. Wenn er den Beitrag kommentiert (und daher den Beitrags-Feed mit dem Grund "Kommentar" abonniert), möchte ich, dass er benachrichtigt wird, wenn andere Benutzer Kommentare zum selben Beitrag hinzufügen. Das Feld "Grund" hilft mir bei dieser Unterscheidung (ich habe es über eine ActivityFilter-Klasse implementiert) zusammen mit den Benachrichtigungseinstellungen des Benutzers.quelle
Es gibt ein aktuelles Format für Aktivitätsströme, das von einer Reihe bekannter Personen entwickelt wird.
http://activitystrea.ms/ .
Grundsätzlich hat jede Aktivität einen Akteur (der die Aktivität ausführt), ein Verb (die Aktion der Aktivität), ein Objekt (an dem der Akteur arbeitet) und ein Ziel.
Zum Beispiel: Max hat einen Link zu Adams Wand gepostet.
Die JSON-Spezifikation hat zum Zeitpunkt des Schreibens die Version 1.0 erreicht, in der das Muster für die Aktivität angezeigt wird, die Sie anwenden können.
Ihr Format wurde bereits von BBC, Gnip, Google Buzz Gowalla, IBM, MySpace, Opera, Socialcast, Superfeedr, TypePad, Windows Live, YIID und vielen anderen übernommen.
quelle
Ich denke, dass eine Erklärung zur Funktionsweise des Benachrichtigungssystems auf großen Websites in der Frage zum Stapelüberlauf enthalten ist, wie Websites für soziale Netzwerke Freunde-Updates berechnen. , in der Antwort der Jeremy Wall . Er schlägt die Verwendung von Message Qeue vor und gibt zwei Open Source-Softwareprogramme an, die diese implementieren:
Siehe auch die Frage Wie lässt sich ein sozialer Aktivitätsstrom am besten implementieren?
quelle
Sie benötigen unbedingt eine performante und verteilte Nachrichtenwarteschlange. Aber es endet nicht damit, dass Sie entscheiden müssen, was als persistente Daten und was als vorübergehend usw. gespeichert werden soll.
Wie auch immer, es ist wirklich eine schwierige Aufgabe, mein Freund, wenn Sie nach einem leistungsstarken und skalierbaren System suchen. Aber natürlich haben einige großzügige Ingenieure ihre Erfahrungen damit geteilt. LinkedIn hat kürzlich sein Nachrichtenwarteschlangensystem Kafka zu Open Source gemacht. Zuvor hatte Facebook Scribe bereits für die Open Source-Community bereitgestellt. Kafka ist in Scala geschrieben und es dauert zunächst einige Zeit, bis es ausgeführt wird, aber ich habe es mit ein paar virtuellen Servern getestet. Es ist sehr schnell.
http://blog.linkedin.com/2011/01/11/open-source-linkedin-kafka/
http://incubator.apache.org/kafka/index.html
quelle
Anstatt Ihren eigenen zu rollen, können Sie sich an einen Dienst eines Drittanbieters wenden, der über eine API verwendet wird. Ich habe ein Collabinate ( http://www.collabinate.com ) gestartet, das über ein Graphendatenbank- Backend und einige ziemlich ausgefeilte Algorithmen verfügt, mit denen große Datenmengen auf eine sehr gleichzeitige und leistungsstarke Weise verarbeitet werden können. Es verfügt zwar nicht über die Funktionen, die Facebook oder Twitter bieten, ist jedoch für die meisten Anwendungsfälle mehr als ausreichend, in denen Sie Aktivitätsströme, soziale Feeds oder Microblogging-Funktionen in eine Anwendung integrieren müssen.
quelle