Zusammenfassung : Für ungefähr 1 Million aktive Benutzer und 150 Millionen gespeicherte Aktivitäten halte ich es einfach:
- Verwenden Sie eine relationale Datenbank zum Speichern eindeutiger Aktivitäten (1 Datensatz pro Aktivität / "Ereignis"). Machen Sie die Datensätze so kompakt wie möglich. Strukturieren Sie diese so, dass Sie schnell einen Stapel von Aktivitäten nach Aktivitäts-ID oder mithilfe einer Reihe von Freund-IDs mit zeitlichen Einschränkungen abrufen können.
- Veröffentlichen Sie die Aktivitäts-IDs bei jeder Erstellung eines Aktivitätsdatensatzes in Redis und fügen Sie die ID einer Liste "Aktivitätsdatenstrom" für jeden Benutzer hinzu, der ein Freund / Abonnent ist, der die Aktivität sehen soll.
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:
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
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 sind user_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:
- Erstellen Sie Ihren MySQL-Aktivitätsdatensatz
- Schieben Sie für jeden Freund des Benutzers, der die Aktivität erstellt hat, die ID in seine Aktivitätsliste in Redis.
- Schneiden Sie jede Liste auf die letzten X Elemente
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.