Benachrichtigungssystem für soziale Netzwerke

10

Hintergrund

Ich arbeite an einer App für einen Kunden, die einige Funktionen für soziale Netzwerke enthält. Ich habe ursprünglich das mobile Front-End entwickelt, aber die Umstände haben mich auch für die Entwicklung des Back-End verantwortlich gemacht.

Als allgemeiner Hintergrund ermöglicht unser System Benutzern, anderen Benutzern zu folgen und Benachrichtigungen über diejenigen zu erhalten, denen sie folgen, wie Sie es von einem sozialen Netzwerk erwarten würden. Eine Einschränkung ist, dass nur eine kleine Teilmenge (höchstens einige hundert) Benutzer verfolgt werden kann, mit der Erwartung, dass der größte Teil der Benutzer mindestens einer dieser Personen folgt.

Auf der UI-Seite befindet sich eine Benachrichtigungsschaltfläche mit einer Nummer. Wenn Sie auf die Schaltfläche klicken, gelangen Sie zum Benachrichtigungsbildschirm.

Das Problem

Ich habe nach Strategien zur Implementierung von Benachrichtigungen gesucht und die meisten Ressourcen, die ich gefunden habe, weisen darauf hin, eine oder mehrere Benachrichtigungstabellen in der Datenbank zu erstellen. (Ein Beispiel, das mir gefällt, ist die akzeptierte Antwort hier: /programming/9735578/building-a-notification-system ).

Was mich abschreckt, ist, dass die meisten datenbankgesteuerten Strategien für Benachrichtigungen das Einfügen einer Zeile für jede Benachrichtigung für jeden Follower erfordern. Wenn also tausend Leute Sally folgen, fügen wir tausend Zeilen in die entsprechende Tabelle ein. Ist das skalierbar? Was passiert, wenn wir den Punkt erreichen, an dem Zehntausende oder Hunderttausende von Benutzern Sally folgen und sie ein paar Dutzend Posts pro Tag erstellt?

Meine ursprüngliche Idee war es, alles mit Abfragen zu behandeln: Die Nummer auf der Benachrichtigungsschaltfläche wurde erhalten, indem Zeilenanzahl für Inhalte angefordert wurde, die kürzlich als beim letzten Besuch des Benachrichtigungsbildschirms veröffentlicht wurden, während einzelne Benachrichtigungen aus detaillierteren Abfragen generiert wurden als Sie den Benachrichtigungsbildschirm besucht haben. Dieser Ansatz würde keine Schreibvorgänge oder zusätzlichen Speicherplatz erfordern, ist jedoch unflexibel und würde den Server wahrscheinlich ziemlich hart treffen.

KONFIGURATION

Das Backend (wie vom vorherigen Entwickler eingerichtet) verwendet CodeIgniter und eine MySQL- Datenbank. Es läuft derzeit auf einem beschissenen GoDaddy-Shared-Hosting-Konto, aber ich gehe davon aus (hoffe?), Dass dieses aktualisiert wird, bevor wir in Produktion gehen, und das Hosting-Paket wird mit dem Benutzerwachstum skaliert.

Derzeit ist unser einziges Front-End eine mobile App, aber wir planen, später auch eine Website zu erstellen. Ich bin derzeit nicht daran interessiert, Push-Updates in Echtzeit vom Server über die Benachrichtigungen zu erhalten.

NACHTRAG

Ich bin nicht auf Backends spezialisiert und bin in dieser Abteilung überfordert. Der Kunde weiß es, und ich habe mein Bestes getan, um den Umfang eines Projekts dieser Art zu erklären, aber er hat klargestellt, dass er zu diesem Zeitpunkt niemandem vertrauen wird, an dem Projekt zu arbeiten. Wir haben wahrscheinlich noch einen Monat Arbeit vor uns, bevor wir mit dem Hinzufügen von Testern beginnen können und ich jede Art von Leistungsmetrik erhalten kann. Ich kann wirklich nicht abschätzen, wie viele Benutzer wir haben oder auf welcher Hardware wir in den nächsten 5 Jahren arbeiten werden, aber ich denke, der Kunde hofft auf Hunderttausende von Benutzern oder mehr.

Ich hoffe, dass dies spezifisch genug für ein Problem ist, um hier veröffentlicht zu werden. Ich kann es bei Bedarf verfeinern. Bitte fragen Sie, wenn Sie Fragen haben oder ich wichtige Details ausgelassen habe.

tl; dr

  • Hat ein datenbankgesteuertes Benachrichtigungssystem negative Auswirkungen auf die langfristige Skalierbarkeit, wenn alle Benutzer nur einigen der wenigen hundert Personen folgen?
  • Gibt es eine Möglichkeit, die Benachrichtigungen datenbankgesteuert zu gestalten, ohne dass für jede Benachrichtigung für jeden Follower eine separate Benachrichtigungszeile erforderlich ist?
  • Wäre ein vollständig abfragegesteuertes Benachrichtigungssystem skalierbar oder hätte es Vorteile, außer keine Daten in die Datenbank zu schreiben?
  • Überdenke ich das zu früh? Sollte ich nur etwas bauen, das jetzt funktioniert, und wir können uns Sorgen machen, es zu optimieren, wenn es zu einem Problem wird, da der Kunde ein begrenztes Budget hat und wir noch nicht wissen, ob das Endprodukt beliebt sein wird?
user45623
quelle
Können Sie Benachrichtigungen ablaufen lassen? Löschen Sie beispielsweise alles, was älter als 2 Wochen ist. Dies sollte mehr oder weniger die Größe der Tabelle ausgleichen, die bei der Reifung der Site verwendet wird.
Großmeister
Das ist kein Problem. Ich war mehr besorgt über die Auswirkungen auf die Leistung, wenn die Datenbank gesperrt wird und jedes Mal, wenn ein beliebter Benutzer einen Beitrag verfasst, 50.000 Einträge in die Benachrichtigungstabelle geschrieben werden.
user45623
Ich habe an einem Projekt mit einem ähnlichen (aber kleineren) Benachrichtigungssystem gearbeitet. Ich hatte einen Hintergrundprozess, der eine Warteschlange mit neuen Posts untersuchte und die Benachrichtigungen behandelte (in diesem Fall wurde tatsächlich eine E-Mail zum Senden in eine zweite Warteschlange eingefügt). Es war keine Echtzeit, aber im Allgemeinen wurde alles innerhalb weniger Minuten erledigt.
Großmeister

Antworten:

10

Wenn also tausend Leute Sally folgen, fügen wir tausend Zeilen in die entsprechende Tabelle ein. Ist das skalierbar?

Ja, vorausgesetzt, die Datenbanktabellen sind ordnungsgemäß indiziert.

Was passiert, wenn wir den Punkt erreichen, an dem Zehntausende oder Hunderttausende von Benutzern Sally folgen und sie ein paar Dutzend Posts pro Tag erstellt?

Sie generieren ein paar Dutzend Zehntausende oder Hunderttausende von Benachrichtigungsdatensätzen pro Tag für Sally, vorausgesetzt, Sie möchten jede Benachrichtigung auf Dauer verfolgen. Der Prozentsatz der Benutzer wie Sally mit dieser Art von Verkehr ist immer sehr gering.

Meine ursprüngliche Idee war es, alles mit Abfragen zu behandeln: Die Nummer auf der Benachrichtigungsschaltfläche wurde erhalten, indem Zeilenanzahl für Inhalte angefordert wurde, die kürzlich als beim letzten Besuch des Benachrichtigungsbildschirms veröffentlicht wurden, während einzelne Benachrichtigungen aus detaillierteren Abfragen generiert wurden als Sie den Benachrichtigungsbildschirm besucht haben.

Dies scheint unnötig kompliziert. Wenn Sie detaillierte Statistiken zu Benachrichtigungen benötigen, speichern Sie einfach die Benachrichtigungen.

Hat ein datenbankgesteuertes Benachrichtigungssystem negative Auswirkungen auf die langfristige Skalierbarkeit, wenn alle Benutzer nur einigen der wenigen hundert Personen folgen?

Deshalb funktioniert es ... eine kleine Anzahl von Menschen erzeugt immer den größten Teil des Verkehrs.

Gibt es eine Möglichkeit, die Benachrichtigungen datenbankgesteuert zu gestalten, ohne dass für jede Benachrichtigung für jeden Follower eine separate Benachrichtigungszeile erforderlich ist?

Ja ... Speichern Sie die Benachrichtigungen nicht. Senden Sie einfach die Benachrichtigungs-E-Mails im Fire-and-Forget-Stil. Oder speichern Sie die Benachrichtigungen für einen bestimmten Zeitraum und verwerfen Sie sie dann. Oder verwerfen Sie jede Benachrichtigung, nachdem sie gelesen wurde.

Wäre ein vollständig abfragegesteuertes Benachrichtigungssystem skalierbar oder hätte es Vorteile, außer keine Daten in die Datenbank zu schreiben?

Ich bin mir nicht sicher, was du damit meinst. Wenn Sie Benachrichtigungen abfragen möchten, müssen Sie diese in der Datenbank speichern. Ansonsten gibt es nichts abzufragen.

Überdenke ich das zu früh?

Sprechen Sie mit jemandem, der Ihnen beim Entwerfen einer ordnungsgemäß normalisierten, indizierten Datenbank mit den richtigen Tabellen helfen kann. Ich sehe keinen Grund, warum eine solche Datenbank die von Ihnen beschriebenen Szenarien nicht effektiv verarbeiten kann.

Ein reales Beispiel

Soweit ich weiß, speichert Stack Exchange alles auf Dauer, einschließlich aller Benachrichtigungen. Sie verwenden eine Datenbanktechnologie ähnlich wie MySQL und einige Caching-Technologien. Während ihre Hardware und ihr Speicherplatz beträchtlich sind, ist die Menge an Verkehr, die sie erhalten, ein gutes Problem.

Robert Harvey
quelle
Wow, du hast alles angesprochen! Danke, Robert! Die Datenbank ist normalisiert, aber ich habe mir die Indizierung noch nicht angesehen. Leider kann ich nicht "mit jemandem sprechen, der mir helfen kann", da die Bedingungen streng sind, dass ich bestimmte Details des Projekts mit niemandem besprechen kann und der Kunde so weit gekommen ist, dass er niemandem vertraut aber ich über das Projekt ... Nun, ich sollte in der Lage sein, etwas über die Indizierung zu recherchieren. Vielen Dank!
user45623
1
Allgemeine Faustregeln für die Indizierung: Jeder Fremdschlüssel sollte mit möglichen Duplikaten indiziert werden. Jeder Primärschlüssel sollte bereits indiziert sein. Felder, nach denen Sie suchen oder auf die Sie eine WHERE-Klausel anwenden müssen, sollten indiziert werden. das sollten wenige sein.
Robert Harvey
1
Das ist falsch. Dies ist NICHT skalierbar. Für jede "Sally" generieren Sie N Zeilen, wobei N Ihre Anzahl von Benutzern ist. Dies wird schnell zu einem Problem, wenn Sie eine angemessene Anzahl von Benutzern haben. 100 "Sallys", die 10 Mal auf 10.000 Benutzer posten, sind 10 Millionen Zeilen pro Tag - klingt das nicht so gut? Was Sie tatsächlich tun möchten, ist dies umzukehren und eine Zeile pro "Sally" -Post zu erstellen. Alle Benutzer, die Sally folgen, müssen diese anstelle ihrer eigenen persönlichen Kopie abrufen. Natürlich wird dies Probleme verursachen, wenn Sie benutzerspezifische Logik (z. B. Aggregation) benötigen ...
Ben
1
... die Erklärung "Vermeiden Sie eine Reihe pro Post" hier ist offensichtlich ein Strohmann, da die meisten Systeme erfordern, dass diese Posts bleiben. Außerdem vermeiden Sie Abfragen nicht, "weil sie kompliziert sind", sondern weil sie bei der Skalierung des Systems zu einem nicht nachhaltigen Overhead führen.
Ben