Frage

Warum Redis für Warteschlangen?

Ich habe den Eindruck, dass Redis ein guter Kandidat für die Implementierung eines Warteschlangensystems sein kann.Bis zu diesem Zeitpunkt haben wir unsere MySQL-Datenbank mit Polling oder RabbitMQ verwendet.Mit RabbitMQ hatten wir viele Probleme - die Client-Bibliotheken sind sehr schlecht und fehlerhaft und wir möchten nicht zu viele Entwicklerstunden in die Behebung investieren, ein paar Probleme mit der Serververwaltungskonsole usw.Und zumindest vorerst greifen wir nicht nach Millisekunden oder treiben die Leistung ernsthaft voran. Solange ein System über eine Architektur verfügt, die eine Warteschlange intelligent unterstützt, sind wir wahrscheinlich in guter Verfassung.

Okay, das ist also der Hintergrund.Im Wesentlichen habe ich ein sehr klassisches, einfaches Warteschlangenmodell - mehrere Produzenten, die Arbeit produzieren, und mehrere Konsumenten, die Arbeit verbrauchen, und sowohl Produzenten als auch Konsumenten müssen in der Lage sein, intelligent zu skalieren.Es stellt sich als naiv heraus PUBSUB funktioniert nicht, da ich nicht will aller abonnenten, die Arbeit konsumieren, ich möchte nur ein abonnent, um die Arbeit zu erhalten.Auf den ersten Blick sieht es für mich so aus BRPOPLPUSH ist ein intelligentes Design.

Können wir BRPOPLPUSH verwenden?

Das Grunddesign mit BRPOPLPUSH haben Sie eine Arbeitswarteschlange und eine Fortschrittswarteschlange.Wenn ein Verbraucher Arbeit erhält, schiebt er den Artikel atomar in die Fortschrittswarteschlange, und wenn er die Arbeit abschließt, schiebt er ihn LREMist es.Dies verhindert ein Blackholing der Arbeit, wenn Kunden sterben, und macht die Überwachung ziemlich mühelos - zum Beispiel können wir feststellen, ob ein Problem vorliegt, das dazu führt, dass Verbraucher lange brauchen, um Aufgaben auszuführen, und ob es eine große Anzahl von Aufgaben gibt.

Es gewährleistet

  • die Arbeit wird an genau einen Verbraucher geliefert
  • die Arbeit wird in einer Fortschrittswarteschlange angezeigt, sodass sie nicht schwarz werden kann, wenn ein Verbraucher

Nachteil

  • Es kommt mir ziemlich seltsam vor, dass das beste Design, das ich gefunden habe, nicht wirklich verwendet wird PUBSUB da scheint es das zu sein, worauf sich die meisten Blogposts über das Anstehen über Redis konzentrieren.Ich habe also das Gefühl, dass mir etwas Offensichtliches fehlt.Der einzige Weg, den ich sehe, zu benutzen PUBSUB ohne Aufgaben zweimal zu verbrauchen, müssen Sie einfach eine Benachrichtigung senden, dass die Arbeit eingetroffen ist, die die Verbraucher dann nicht blockieren können RPOPLPUSH.
  • Es ist unmöglich, mehr als ein Arbeitselement gleichzeitig anzufordern, was ein Leistungsproblem zu sein scheint.Für unsere Situation keine große, aber es sagt offensichtlich, dass dieser Vorgang nicht für einen hohen Durchsatz oder diese Situation ausgelegt war
  • Kurz: vermisse ich etwas Dummes?

Auch Knoten hinzufügen.js-Tag, weil das die Sprache ist, mit der ich mich hauptsächlich beschäftige.Node bietet möglicherweise einige Vereinfachungen bei der Implementierung, da es Single-Threaded und nicht blockierend ist, aber außerdem verwende ich die node-Redis-Bibliothek, und Lösungen sollten oder können auch auf ihre Stärken und Schwächen reagieren.

War es hilfreich?

Lösung

Wenn Sie Redis für eine Nachrichtenwarteschlange im Knoten verwenden möchten.js und es macht Ihnen nichts aus, dafür ein Modul zu verwenden, dann können Sie es versuchen RSMQ - die Redis Einfache Nachrichtenwarteschlange für Knoten.Es war zu dem Zeitpunkt, als diese Frage gestellt wurde, nicht verfügbar, aber heute ist es eine praktikable Option.

Wenn du wirklich willst implementieren die Warteschlange selbst, wie Sie in Ihrer Frage angegeben haben, dann möchten Sie vielleicht die Quelle von RSMQ lesen, da es nur 20 Code-Bildschirme sind, die genau das tun, wonach Sie fragen.

Sehen:

Andere Tipps

Ich bin bisher auf einige Schwierigkeiten gestoßen, die ich hier dokumentieren möchte.

Wie gehen Sie mit Reconnect Logic um?

Dies ist ein schwieriges Problem und ein besonders schwieriges Problem beim Entwerfen und Implementieren einer Nachrichtenwarteschlange.Nachrichten müssen irgendwo in die Warteschlange gestellt werden können, wenn Verbraucher offline sind, sodass ein einfaches Pub-Sub nicht stark genug ist und Verbraucher sich im Abhörzustand wieder verbinden müssen. Blockierende Pops sind schwer zu pflegen, da sie ein nicht idempotenter Abhörzustand sind.Das Abhören sollte eine idempotente Operation sein, aber wenn Sie sich mit einer Trennung in Bezug auf einen blockierenden Pop befassen, haben Sie das Vergnügen, sehr genau darüber nachzudenken, ob die Trennung unmittelbar nach dem Erfolg der Operation oder kurz vor dem Fehlschlagen der Operation stattgefunden hat.Das ist nicht unüberwindbar, aber es ist unerwünscht.

Des Weiteren sollte der Abhörvorgang sein so einfach wie möglich. Idealerweise sollte es diese Eigenschaften haben:

  • Zuhören ist idempotent.
  • Der Verbraucher ist immer die Abhör- und Drossellogik wird außerhalb des Abhörlogikcodes verarbeitet.RabbitMQ kapselt dies ein, indem der Verbraucher die Anzahl der nicht gepackten Nachrichten, die er haben kann, festlegen kann.
    Insbesondere habe ich mich für ein schlechtes Design entschieden, bei dem das Wiedereintreten in einen blockierenden Pop vom Erfolg früherer Operationen abhing, was spröde war und hartes Nachdenken erforderte.

Ich bevorzuge jetzt eine Redis PUBSUB + RPOPLPUSH-Lösung.Dies entkoppelt die Benachrichtigung über Arbeit vom Arbeitsverbrauch, wodurch wir eine saubere Abhörlösung ausklammern können. Der PUBSUB ist nur für die Meldung von Arbeiten verantwortlich. Die atomare Natur von RPOPLPUSH ist für den Konsum verantwortlich und delegiert die Arbeit an genau einen Verbraucher.Anfangs schien diese Lösung im Vergleich zu einem blockierenden Pop unnötig kompliziert zu sein, aber jetzt sehe ich, dass die Komplikation überhaupt nicht unnötig war;es löste ein schwieriges Problem.

Diese Lösung ist jedoch nicht ganz trivial:

  • verbraucher sollten auch nach Arbeiten an der Wiederverbindung suchen.
  • verbraucher möchten vielleicht sowieso eine Umfrage für neue Arbeit machen, für Redundanz.Sollte die Umfrage tatsächlich erfolgreich sein, sollte eine Warnung ausgegeben werden, da dies nur zwischen dem Konsum auf dem PUBSUB und der Umfrage auf einem RPOPLPUSH geschehen sollte.Daher deuten viele Umfrageerfolge auf ein kaputtes Abonnementsystem hin.

Beachten Sie, dass das PUBSUB / RPOPLPUSH-Design auch Skalierungsprobleme aufweist. Jeder der Verbraucher erhält eine einfache Benachrichtigung über jeder nachricht, was bedeutet, dass dies einen unnötigen Engpass aufweist.Ich vermute, dass es möglich ist, Kanäle zu verwenden, um die Arbeit zu scherben, aber dies ist wahrscheinlich ein schwieriges Design, um gut zu funktionieren.

Der Hauptgrund für die Verwendung von RabbitMQ gegenüber Redis sind also die Fehlerszenarien und das Clustering.

Dieser Artikel erklärt es wirklich am besten, also stelle ich nur den Link zur Verfügung:

https://aphyr.com/posts/283-jepsen-redis

Redis Sentinel und in jüngerer Zeit redis Clustering sind nicht in der Lage, eine Reihe sehr grundlegender Fehlerszenarien zu bewältigen, die es zu einer schlechten Wahl für eine Warteschlange machten.

RabbitMQ hat seine eigenen Probleme, aber abgesehen davon ist es unglaublich solide in der Produktion und eine gute Nachrichtenwarteschlange.

Hier ist der Beitrag für Kaninchen:

https://aphyr.com/posts/315-jepsen-rabbitmq

Wenn Sie sich das CAP-Theorum (Konsistenz, Verfügbarkeit und Partitionsbehandlung) ansehen, können Sie nur 2 von 3 auswählen.Wir nutzen RMQ für die CP (Konsistenz- und Partitionsbehandlung) mit unserer Nachrichtenlast. Wenn wir nicht verfügbar sind, ist dies nicht das Ende der Welt.Um keine Nachrichten zu verlieren, verwenden wir ignore für die Partitionsbehandlung, um keine Nachrichten zu verlieren.Duplikate können behandelt werden, da die Quelle die UUID verwaltet.

Lizenziert unter: CC-BY-SA mit Zuschreibung
scroll top