Implementieren der Aktualisierung von Upvote / Downvote dynamisch

8

So implementieren Sie eine dynamische Aktualisierung der Stimmenanzahl ähnlich wie bei quora: - Immer wenn ein Benutzer eine Antwort upvotet, wird diese automatisch für jeden angezeigt, der diese Seite anzeigt.

Ich bin auf der Suche nach einer Antwort, die folgende Adresse:

  • Müssen wir für jede Antwort nach einer positiven Bewertung Ausschau halten, wenn ja dann, wie man die Serverlast, die wegen so vieler Benutzer entsteht, managt Polling für Upvotes.
  • Oder websockits / Push-Benachrichtigungen zu verwenden, wie skalierbar sind diese?
  • Wie wird die Anzahl der Upvotes / Downvotes in Datenbanken / Inmemory gespeichert, um dies zu unterstützen? Wie kontrollieren sie die Anzahl der Lese- / Schreibvorgänge? Meine Backend-Datenbank ist mysql

Die Antwort, nach der ich suche, ist vielleicht nicht genau so, wie quora es tut, aber vielleicht ist es so, dass dies mit verfügbaren Opensource-Technologien gemacht werden kann.

    
akshay202 06.02.2014, 10:05
quelle

3 Antworten

4

Es sind nicht die Details des Backend-Systems, über die Sie sich Sorgen machen müssen, sondern das Frontend. Dass die Verbindung immer offen ist, ist in jedem realen Maßstab unpraktisch. Stattdessen möchten Sie das Gegenteil - in der Lage zu sein, zu dienen und die Verbindung vom Back-End so schnell wie möglich zu schließen.

Websockets ist eine sexy Technologie, aber auch hier gibt es Probleme mit Proxies Wenn Sie etwas entwickeln, das auf einer Vielzahl von Bildschirmen (Desktop, Tablet, Handy) funktionieren sollte, könnte dies für Sie ein Problem darstellen. Selbst gute alte Umfragen funktionieren möglicherweise nicht durch Firewalls und Proxies.

Hier ist eine gute Nachricht: Ich denke

  

"polling upvote counts für jede Antwort"

ist in diesem Fall eine vollkommen gute Lösung. Berücksichtigen Sie Folgendes:

  • Ihr Anwendungsfall benötigt keine echten Echtzeit-Updates. Es ist wenig schädlich zu sehen, dass der Zähler ein wenig später aktualisiert wird
  • für sehr beliebte Themen würden Sie gerne mehrere Ups / Downs stimmen, trotzdem in eins
  • In den meisten Themen wird es Tage / Wochen überhaupt keinen Aufwärts- / Abwärtsvotum-Verkehr geben. Daher ist es eine Verschwendung, eine Verbindung offen zu halten und auf ein Ereignis zu warten, das niemals kommt
  • Die meisten Benutzer werden nie nach oben / unten abstimmen, was gerade zum Lesen eines Themas gekommen ist, so dass Ihre Lese- / Schreib-Rate von Themen-Statistiken stark in Richtung Lesen verschoben wird
  • Netzwerk-Latenz variiert sehr stark zwischen Clients, Sie werden schreckliche Übertragungsraten für eine 100B HTTP-Antworten sehen, während dieser träge Client seine Antwort Byte für Byte Ihre wertvolle Serververbindung holt und was noch wichtiger ist - Thread auf einem Back-End Server ist beschäftigt

Hier ist, womit ich anfangen würde:

  • haben die Browser regelmäßig nach einer neuen Topic-Statistik gefragt, nachdem die Hauptseite geladen wurde
  • behalte dein MySQL, behalte Zähler dort. Bei jeder Up / Down-Abstimmung aktualisieren Sie die DB
  • lege Memcached als Write-through-Cache vor die DB, d. h. jedes Mal, wenn ein Up / Down-Vote-Update-Cache vorhanden ist, aktualisiere die DB. Legen Sie die explizite Ablaufzeit für einen Zähler auf 10-15 Minuten fest. Jedes Mal, wenn der Zähler aktualisiert wird, wird die Verfallszeit automatisch verlängert.
  • entwirft diese Polling-HTTP-Aufrufe so, dass sie von HTTP-Proxies im Cache gespeichert werden können, setzen Sie expire und ttl http-Header auf 60 Sekunden
  • setzen Sie einen Reverse-Proxy ( Varnish , nginx ) vor Ihren Front-End-Servern, kann dieser Proxy die abgefragten Anrufe zwischenspeichern. Diese sorgen für den Second-Level-Cache und helfen dabei, Back-End-Server-Threads schneller freizugeben, siehe Netzwerk-Latenzen oben
  • Richten Sie Ihre Reverse-Proxy-Komponente so ein, dass sie direkt mit memcached-Servern kommunizieren kann direkt , ohne einen Aufruf an den Backend-Server zu richten, wenn Sie dies sowohl mit Varnish als auch mit nginx tun können
  • Es gibt kein schickes Schema zum Speichern solcher Daten, es ist eine einfache inc()/dec() -Operation in memcached, beachten Sie, dass es aus Sicht der Racebedingungen sicher ist. Es ist auch eine sichere atomare Operation in MySQL UPDATE table SET field = field + 1 WHERE [...]

Aggressives Multilevel-Caching deckt Ihren read -Pfad ab: Beachten Sie, dass diese HTTP-Abfrageanforderungen in Memcached und in allen HTTP-Caches auf der Kanten .

Um den langen Schwanz des unpopulären Themas zu kümmern - make http ttl für solche Antworten umgekehrt proportional zur Popularität.

Eine Leseanforderung wird nur selten zum Front-End-Server gelangen, wenn der HTTP-Cache abgelaufen ist und memcached ihn auch nicht hat. Wenn das immer noch ein Problem ist, fügen Sie memecached Server hinzu und erhöhen Sie die Ablaufzeit in memcached auf der ganzen Linie.

Nachdem Sie damit fertig sind, haben Sie alle reads erledigt. Das einzige Problem, das Sie immer noch haben könnten, ist abhängig von der Skalierung eine hohe Rate von writes , d. H. Der Fluss von Aufwärts- / Abwärtsstimmen. Hier kann es vorkommen, dass Ihre einzelne MySQL-Instanz einige Verzögerungen anzeigt. Fürchte dich nicht - gehe auf dem alten Pfad der Scharfschaltung deiner Instanzen vor oder füge einen NoSQL-Speicher nur für Counter hinzu.

Verwenden Sie kein Messaging-System, es sei denn, es ist absolut notwendig, oder Sie möchten eine Ausrede haben, damit zu spielen.

    
Igor Katkov 15.02.2014, 07:45
quelle
5

WebSockets, Server-gesendete Ereignisse (ich glaube, das haben Sie mit Push-Benachrichtigungen gemeint) und AJAX-Long-Polling haben den gleichen Nachteil - sie behalten die zugrundeliegende TCP-Verbindung für lange Zeit offen Die Frage ist also, wie viele offene TCP-Verbindungen ein Server handhaben kann. Grundsätzlich hängt es von seinem Betriebssystem, der Anzahl der Dateideskriptoren (einem Konfigurationsparameter) und dem verfügbaren Speicher ab (jede offene Verbindung reserviert einen Lese- / Schreibpuffer). Hier ist mehr dazu .

Wir haben einmal eine Möglichkeit getestet, 1 Million Websocket-Verbindungen auf einem einzigen Server offen zu halten (Windows 7 x64 mit 16 GB RAM, JVM 1.7 mit 8 GB Heap, mit Undertow-Beta , um Web-Anfragen zu bedienen. Überraschenderweise war der schwierigste Teil, die Last auf dem Server zu generieren) Es hat geschafft, 1M zu halten. Aber wieder hat der Server nichts Nützliches getan, nur Anfragen erhalten, Protokoll-Upgrade durchlaufen und diese Verbindungen offen gehalten. Es gab auch einige verlorene Verbindungen, aus welchen Gründen auch immer. Wir haben das nicht untersucht. Aber in der Produktion müssten Sie auch den Server anpingen und die Verbindung wiederherstellen.

Abgesehen davon, Websockets scheinen hier ein Overkill, SSE sind immer noch nicht weit verbreitet. Also würde ich mit guten alten AJAX-Abfragen gehen, aber so viel wie möglich optimieren.
Funktioniert überall, einfach zu implementieren und zu optimieren, ohne auf ein externes System angewiesen zu sein (ich hatte mehrere Male schlechte Erfahrungen damit), Möglichkeiten zur Optimierung. Beispielsweise könnten Sie Updates für alle geöffneten Artikel in einem einzigen Browser gruppieren oder das Aktualisierungsintervall entsprechend der Beliebtheit des Artikels anpassen.
Schließlich scheint es nicht so, als ob Sie hier Echtzeit-Benachrichtigungen benötigen.

    
Yuri 14.02.2014 14:58
quelle
2

klingt so, als könnten Sie ein Nachrichtensystem wie Kafka oder RabbitMQ oder ActiveMQ verwenden. Ihr Frontend würde Stimmen an einen Nachrichtenkanal senden und sie mit einem Listener empfangen, und Sie könnten ein Server-Side-Piece haben, das die Stimmen regelmäßig an die db weitergibt.

Sie können Ihre Aufgabe auch ausführen, indem Sie Ihre Datenbank abfragen, und indem Sie eine mit einem Post verknüpfte Nummer über ein gespeichertes Proc erhöhen / dekrementieren ... gibt es eine Reihe von Optionen hier und es hängt davon ab, wie viel Nebenläufigkeit Sie sein mögen gegenüber.

    
markg 09.02.2014 14:56
quelle