RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern

Fehlertoleranz und Hochverfügbarkeit sind große Themen, daher widmen wir RabbitMQ und Kafka separate Artikel. In diesem Artikel geht es um RabbitMQ und im nächsten um Kafka im Vergleich zu RabbitMQ. Dies ist ein langer Artikel, also machen Sie es sich bequem.

Schauen wir uns die Strategien für Fehlertoleranz, Konsistenz und Hochverfügbarkeit (HA) sowie die Kompromisse an, die jede Strategie mit sich bringt. RabbitMQ kann auf einem Cluster von Knoten ausgeführt werden – und wird dann als verteiltes System klassifiziert. Wenn es um verteilte Systeme geht, sprechen wir oft von Konsistenz und Verfügbarkeit.

Diese Konzepte beschreiben, wie sich ein System verhält, wenn es ausfällt. Netzwerkverbindungsfehler, Serverfehler, Festplattenfehler, vorübergehende Nichtverfügbarkeit des Servers aufgrund von Garbage Collection, Paketverlust oder Verlangsamung der Netzwerkverbindung. All dies kann zu Datenverlust oder Konflikten führen. Es stellt sich heraus, dass es praktisch unmöglich ist, ein System einzurichten, das sowohl vollständig konsistent (kein Datenverlust, keine Datendivergenz) als auch für alle Fehlerszenarien verfügbar ist (es akzeptiert Lese- und Schreibvorgänge).

Wir werden sehen, dass Konsistenz und Verfügbarkeit an entgegengesetzten Enden des Spektrums liegen und Sie entscheiden müssen, welchen Weg Sie optimieren möchten. Die gute Nachricht ist, dass diese Wahl mit RabbitMQ möglich ist. Sie haben diese Art von „nerdigen“ Hebeln, um das Gleichgewicht hin zu mehr Konsistenz oder besserer Zugänglichkeit zu verschieben.

Wir werden ein besonderes Augenmerk darauf legen, welche Konfigurationen aufgrund bestätigter Datensätze zu Datenverlusten führen. Es gibt eine Verantwortungskette zwischen Herausgebern, Maklern und Verbrauchern. Sobald die Nachricht an den Broker übermittelt wurde, ist es seine Aufgabe, die Nachricht nicht zu verlieren. Wenn der Broker den Empfang der Nachricht durch den Herausgeber bestätigt, gehen wir nicht davon aus, dass sie verloren geht. Aber wir werden sehen, dass dies tatsächlich passieren kann, abhängig von Ihrer Broker- und Publisher-Konfiguration.

Einzelknoten-Resilienzprimitive

Resiliente Warteschlangen/Routing

In RabbitMQ gibt es zwei Arten von Warteschlangen: dauerhafte und nicht dauerhafte. Alle Warteschlangen werden in der Mnesia-Datenbank gespeichert. Dauerhafte Warteschlangen werden beim Knotenstart erneut angekündigt und überstehen somit Neustarts, Systemabstürze oder Serverabstürze (solange die Daten bestehen bleiben). Das bedeutet, dass die Warteschlangen-/Routing-Infrastruktur wieder online ist, solange Sie Routing (Austausch) und Warteschlange als belastbar deklarieren.

Volatile Warteschlangen und Routing werden entfernt, wenn der Knoten neu gestartet wird.

Permanente Nachrichten

Nur weil eine Warteschlange dauerhaft ist, bedeutet das nicht, dass alle ihre Nachrichten einen Knotenneustart überstehen. Nur vom Herausgeber festgelegte Nachrichten nachhaltig (hartnäckig). Persistente Nachrichten belasten den Broker zwar zusätzlich, aber wenn der Nachrichtenverlust nicht akzeptabel ist, gibt es keine andere Option.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 1. Nachhaltigkeitsmatrix

Clustering mit Warteschlangenspiegelung

Um den Verlust eines Maklers zu überstehen, brauchen wir Redundanz. Wir können mehrere RabbitMQ-Knoten zu einem Cluster zusammenfassen und dann zusätzliche Redundanz hinzufügen, indem wir Warteschlangen zwischen mehreren Knoten replizieren. Wenn ein Knoten ausfällt, gehen auf diese Weise keine Daten verloren und wir bleiben verfügbar.

Warteschlangenspiegelung:

  • eine Hauptwarteschlange (Master), die alle Schreib- und Lesebefehle empfängt
  • ein oder mehrere Spiegel, die alle Nachrichten und Metadaten von der Hauptwarteschlange empfangen. Diese Spiegel dienen nicht der Skalierung, sondern dienen lediglich der Redundanz.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 2. Warteschlangenspiegelung

Die Spiegelung wird durch die entsprechende Richtlinie festgelegt. Darin können Sie den Replikationskoeffizienten und sogar die Knoten auswählen, auf denen sich die Warteschlange befinden soll. Beispiele:

  • ha-mode: all
  • ha-mode: exactly, ha-params: 2 (ein Master und ein Spiegel)
  • ha-mode: nodes, ha-params: rabbit@node1, rabbit@node2

Bestätigung des Herausgebers

Um eine konsistente Aufzeichnung zu erreichen, sind Herausgeberbestätigungen erforderlich. Ohne sie besteht die Gefahr, dass Nachrichten verloren gehen. Nachdem die Nachricht auf die Festplatte geschrieben wurde, wird eine Bestätigung an den Herausgeber gesendet. RabbitMQ schreibt Nachrichten nicht beim Empfang auf die Festplatte, sondern in regelmäßigen Abständen im Bereich von mehreren hundert Millisekunden. Wenn eine Warteschlange gespiegelt wird, wird eine Bestätigung erst gesendet, nachdem auch alle Spiegel ihre Kopie der Nachricht auf die Festplatte geschrieben haben. Das bedeutet, dass die Verwendung von Bestätigungen die Latenz erhöht, aber wenn die Datensicherheit wichtig ist, dann sind sie notwendig.

Failover-Warteschlange

Wenn ein Broker beendet wird oder abstürzt, stürzen auch alle Warteschlangenleiter (Master) auf diesem Knoten ab. Der Cluster wählt dann den ältesten Spiegel jedes Masters aus und befördert ihn zum neuen Master.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 3. Mehrere gespiegelte Warteschlangen und ihre Richtlinien

Broker 3 fällt aus. Beachten Sie, dass der Queue-C-Spiegel auf Broker 2 zum Master heraufgestuft wird. Beachten Sie außerdem, dass für Warteschlange C auf Broker 1 ein neuer Spiegel erstellt wurde. RabbitMQ versucht immer, den in Ihren Richtlinien angegebenen Replikationsfaktor beizubehalten.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 4. Broker 3 fällt aus, was zum Ausfall von Warteschlange C führt

Der nächste Broker 1 fällt! Wir haben nur noch einen Makler. Der Spiegel der Warteschlange B wird zum Master befördert.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Fig. 5

Wir haben Broker 1 zurückgegeben. Unabhängig davon, wie gut die Daten den Verlust und die Wiederherstellung des Brokers überstehen, werden alle gespiegelten Warteschlangennachrichten beim Neustart verworfen. Dies ist wichtig zu beachten, da dies Konsequenzen haben wird. Wir werden uns diese Auswirkungen in Kürze ansehen. Somit ist Broker 1 nun wieder Mitglied des Clusters und der Cluster versucht, die Richtlinien einzuhalten und erstellt daher Spiegelungen auf Broker 1.

In diesem Fall war der Verlust von Broker 1 vollständig, ebenso wie die Daten, sodass die nicht gespiegelte Warteschlange B vollständig verloren ging.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 6. Broker 1 nimmt den Dienst wieder auf

Broker 3 ist wieder online, sodass die Warteschlangen A und B die darauf erstellten Spiegel zurückerhalten, um ihre HA-Richtlinien zu erfüllen. Aber jetzt befinden sich alle Hauptwarteschlangen auf einem Knoten! Dies ist nicht ideal, eine gleichmäßige Verteilung zwischen den Knoten ist besser. Leider gibt es hier nicht viele Möglichkeiten, die Master neu auszubalancieren. Wir werden später auf dieses Problem zurückkommen, da wir uns zunächst mit der Warteschlangensynchronisierung befassen müssen.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 7. Broker 3 nimmt den Dienst wieder auf. Alle Hauptwarteschlangen auf einem Knoten!

Jetzt sollten Sie eine Vorstellung davon haben, wie Spiegel Redundanz und Fehlertoleranz bieten. Dies stellt die Verfügbarkeit bei Ausfall eines einzelnen Knotens sicher und schützt vor Datenverlust. Aber wir sind noch nicht fertig, denn in Wirklichkeit ist es viel komplizierter.

Synchronisation

Beim Erstellen eines neuen Spiegels werden alle neuen Nachrichten immer auf diesen und alle anderen Spiegel repliziert. Was die vorhandenen Daten in der Master-Warteschlange betrifft, können wir sie auf einen neuen Spiegel replizieren, der zu einer vollständigen Kopie des Masters wird. Wir können uns auch dafür entscheiden, vorhandene Nachrichten nicht zu replizieren und die Hauptwarteschlange und den neuen Spiegel rechtzeitig konvergieren zu lassen, wobei neue Nachrichten am Ende der Hauptwarteschlange ankommen und vorhandene Nachrichten am Kopf der Hauptwarteschlange verlassen.

Diese Synchronisierung erfolgt automatisch oder manuell und wird mithilfe einer Warteschlangenrichtlinie verwaltet. Schauen wir uns ein Beispiel an.

Wir haben zwei gespiegelte Warteschlangen. Warteschlange A wird automatisch synchronisiert und Warteschlange B wird manuell synchronisiert. Beide Warteschlangen enthalten zehn Nachrichten.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 8. Zwei Warteschlangen mit unterschiedlichen Synchronisationsmodi

Jetzt verlieren wir Broker 3.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 9. Broker 3 ist gefallen

Broker 3 nimmt seinen Dienst wieder auf. Der Cluster erstellt für jede Warteschlange auf dem neuen Knoten einen Spiegel und synchronisiert die neue Warteschlange A automatisch mit dem Master. Der Spiegel der neuen Queue B bleibt jedoch leer. Auf diese Weise haben wir vollständige Redundanz in Warteschlange A und nur einen Spiegel für vorhandene Nachrichten in Warteschlange B.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 10. Der neue Spiegel von Warteschlange A empfängt alle vorhandenen Nachrichten, der neue Spiegel von Warteschlange B jedoch nicht.

In beiden Warteschlangen kommen zehn weitere Nachrichten an. Dann stürzt Broker 2 ab und Warteschlange A führt ein Rollback zum ältesten Spiegel durch, der sich auf Broker 1 befindet. Bei einem Ausfall kommt es zu keinem Datenverlust. In Warteschlange B gibt es zwanzig Nachrichten im Master und nur zehn im Spiegel, da diese Warteschlange nie die ursprünglichen zehn Nachrichten repliziert hat.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 11. Warteschlange A führt ein Rollback zu Broker 1 durch, ohne dass Nachrichten verloren gehen

In beiden Warteschlangen kommen zehn weitere Nachrichten an. Jetzt stürzt Broker 1 ab. Warteschlange A wechselt problemlos zum Spiegel, ohne dass Nachrichten verloren gehen. Allerdings gibt es in Warteschlange B Probleme. An diesem Punkt können wir entweder die Verfügbarkeit oder die Konsistenz optimieren.

Wenn wir die Barrierefreiheit optimieren wollen, dann die Richtlinie ha-promote-on-failure sollte eingebaut werden immer. Dies ist der Standardwert, sodass Sie die Richtlinie einfach überhaupt nicht angeben können. In diesem Fall lassen wir im Wesentlichen Fehler in nicht synchronisierten Spiegeln zu. Dadurch gehen Nachrichten verloren, die Warteschlange bleibt jedoch lesbar und beschreibbar.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 12. Warteschlange A wird auf Broker 3 zurückgesetzt, ohne dass Nachrichten verloren gehen. Warteschlange B wird mit zehn verlorenen Nachrichten auf Broker 3 zurückgesetzt

Wir können auch installieren ha-promote-on-failure in die Bedeutung when-synced. In diesem Fall wartet die Warteschlange nicht auf den Spiegel zurück, sondern wartet, bis Broker 1 mit seinen Daten in den Online-Modus zurückkehrt. Nach der Rückkehr befindet sich die Hauptwarteschlange ohne Datenverlust wieder auf Broker 1. Die Verfügbarkeit wird der Datensicherheit geopfert. Dies ist jedoch ein riskanter Modus, der sogar zu einem vollständigen Datenverlust führen kann, den wir uns gleich ansehen werden.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 13. Warteschlange B bleibt nach dem Verlust von Broker 1 nicht verfügbar

Sie fragen sich vielleicht: „Ist es besser, niemals die automatische Synchronisierung zu verwenden?“ Die Antwort ist, dass die Synchronisierung ein blockierender Vorgang ist. Während der Synchronisation kann die Hauptwarteschlange keine Lese- oder Schreibvorgänge ausführen!

Schauen wir uns ein Beispiel an. Jetzt haben wir sehr lange Warteschlangen. Wie können sie eine solche Größe erreichen? Aus mehreren Gründen:

  • Warteschlangen werden nicht aktiv genutzt
  • Dies sind Hochgeschwindigkeitswarteschlangen, und im Moment sind die Verbraucher langsam
  • Es sind schnelle Warteschlangen, es gab eine Panne und die Verbraucher holen auf

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 14. Zwei große Warteschlangen mit unterschiedlichen Synchronisationsmodi

Jetzt fällt Broker 3.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 15. Broker 3 fällt, sodass in jeder Warteschlange ein Master und ein Mirror zurückbleiben

Broker 3 geht wieder online und neue Spiegel werden erstellt. Hauptwarteschlange A beginnt mit der Replikation vorhandener Nachrichten auf den neuen Spiegel. Während dieser Zeit ist die Warteschlange nicht verfügbar. Die Replikation der Daten dauert zwei Stunden, was zu einer Ausfallzeit von zwei Stunden für diese Warteschlange führt!

Queue B bleibt jedoch während des gesamten Zeitraums verfügbar. Sie opferte einige Redundanz zugunsten der Zugänglichkeit.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 16. Die Warteschlange bleibt während der Synchronisierung nicht verfügbar

Nach zwei Stunden ist auch Warteschlange A verfügbar und kann wieder Lese- und Schreibvorgänge annehmen.

Updates

Dieses blockierende Verhalten während der Synchronisierung erschwert die Aktualisierung von Clustern mit sehr großen Warteschlangen. Irgendwann muss der Masterknoten neu gestartet werden, was bedeutet, dass entweder zu einem Spiegel gewechselt oder die Warteschlange deaktiviert werden muss, während der Server aktualisiert wird. Wenn wir uns für den Übergang entscheiden, gehen Nachrichten verloren, wenn die Spiegel nicht synchronisiert sind. Standardmäßig wird während eines Broker-Ausfalls kein Failover auf einen nicht synchronisierten Spiegel durchgeführt. Das heißt, sobald der Broker zurückkehrt, verlieren wir keine Nachrichten, der einzige Schaden war eine einfache Warteschlange. Verhaltensregeln für den Fall, dass die Verbindung zu einem Broker getrennt wird, werden durch Richtlinien festgelegt ha-promote-on-shutdown. Sie können einen von zwei Werten festlegen:

  • always= Übergang zu unsynchronisierten Spiegeln ist aktiviert
  • when-synced= Nur Übergang zu einem synchronisierten Spiegel, andernfalls wird die Warteschlange nicht mehr lesbar und nicht mehr beschreibbar. Die Warteschlange wird wieder in Betrieb genommen, sobald der Broker zurückkehrt

So oder so muss man sich bei großen Warteschlangen zwischen Datenverlust und Nichtverfügbarkeit entscheiden.

Wenn Verfügbarkeit die Datensicherheit verbessert

Bevor Sie eine Entscheidung treffen, müssen Sie noch eine weitere Komplikation berücksichtigen. Während die automatische Synchronisierung aus Gründen der Redundanz besser ist, wie wirkt sie sich auf die Datensicherheit aus? Natürlich ist es bei RabbitMQ bei besserer Redundanz weniger wahrscheinlich, dass vorhandene Nachrichten verloren gehen, aber was ist mit neuen Nachrichten von Herausgebern?

Hier müssen Sie Folgendes berücksichtigen:

  • Könnte der Herausgeber einfach einen Fehler zurückgeben und den Upstream-Dienst oder Benutzer veranlassen, es später erneut zu versuchen?
  • Kann der Herausgeber die Nachricht lokal oder in einer Datenbank speichern, um es später noch einmal zu versuchen?

Wenn der Herausgeber die Nachricht nur verwerfen kann, verbessert die Verbesserung der Barrierefreiheit tatsächlich auch die Datensicherheit.

Daher muss ein Gleichgewicht gesucht werden, und die Lösung hängt von der konkreten Situation ab.

Probleme mit ha-promote-on-failure=when-synced

Idee ha-promote-on-failure= wenn synchronisiert besteht darin, dass wir den Wechsel zu einem unsynchronisierten Spiegel verhindern und dadurch Datenverluste vermeiden. Die Warteschlange bleibt unlesbar oder beschreibbar. Stattdessen versuchen wir, den abgestürzten Broker mit intakten Daten wiederherzustellen, damit er ohne Datenverlust wieder als Master fungieren kann.

Aber (und das ist ein großes Aber) wenn der Broker seine Daten verloren hat, dann haben wir ein großes Problem: Die Warteschlange ist verloren! Alle Daten sind weg! Selbst wenn Sie Spiegel haben, die größtenteils mit der Hauptwarteschlange aufholen, werden diese Spiegel ebenfalls verworfen.

Um einen Knoten mit demselben Namen erneut hinzuzufügen, weisen wir den Cluster an, den verlorenen Knoten zu vergessen (mit dem Befehl Rabbitmqctl Forget_cluster_node) und starten Sie einen neuen Broker mit demselben Hostnamen. Während sich der Cluster an den verlorenen Knoten erinnert, merkt er sich die alte Warteschlange und die nicht synchronisierten Spiegel. Wenn ein Cluster angewiesen wird, einen verwaisten Knoten zu vergessen, wird auch diese Warteschlange vergessen. Jetzt müssen wir es neu deklarieren. Wir haben alle Daten verloren, obwohl wir Spiegel mit einem Teildatensatz hatten. Es wäre besser, auf einen nicht synchronisierten Spiegel umzusteigen!

Daher ist eine manuelle Synchronisierung (und ein Fehler bei der Synchronisierung) in Kombination mit ha-promote-on-failure=when-syncedMeiner Meinung nach ziemlich riskant. In den Dokumenten heißt es, dass diese Option aus Gründen der Datensicherheit existiert, aber es ist ein zweischneidiges Messer.

Master-Neuausrichtung

Wie versprochen kehren wir zum Problem der Anhäufung aller Master auf einem oder mehreren Knoten zurück. Dies kann sogar als Folge eines fortlaufenden Cluster-Updates passieren. In einem Cluster mit drei Knoten sammeln sich alle Master-Warteschlangen auf einem oder zwei Knoten.

Das Rebalancing von Mastern kann aus zwei Gründen problematisch sein:

  • Es gibt keine guten Tools, um eine Neuausrichtung durchzuführen
  • Warteschlangensynchronisierung

Für die Neuausrichtung gibt es einen Dritten Plugin, was nicht offiziell unterstützt wird. Bezüglich Drittanbieter-Plugins im RabbitMQ-Handbuch es wird gesagt: „Das Plugin bietet einige zusätzliche Konfigurations- und Berichtstools, wird jedoch vom RabbitMQ-Team nicht unterstützt oder überprüft.“ Benutzung auf eigene Gefahr."

Es gibt einen weiteren Trick, um die Hauptwarteschlange über HA-Richtlinien zu verschieben. Das Handbuch erwähnt Skript dafür. Es funktioniert so:

  • Entfernt alle Spiegel mithilfe einer temporären Richtlinie, die eine höhere Priorität als die vorhandene HA-Richtlinie hat.
  • Ändert die temporäre HA-Richtlinie zur Verwendung des Knotenmodus und gibt den Knoten an, an den die Master-Warteschlange übertragen werden soll.
  • Synchronisiert die Warteschlange für die Push-Migration.
  • Nach Abschluss der Migration wird die temporäre Richtlinie gelöscht. Die anfängliche HA-Richtlinie wird wirksam und die erforderliche Anzahl an Spiegeln wird erstellt.

Der Nachteil besteht darin, dass dieser Ansatz möglicherweise nicht funktioniert, wenn Sie große Warteschlangen oder strenge Redundanzanforderungen haben.

Sehen wir uns nun an, wie RabbitMQ-Cluster mit Netzwerkpartitionen funktionieren.

Verbindungsverlust

Die Knoten eines verteilten Systems sind durch Netzwerkverbindungen verbunden, und Netzwerkverbindungen können und werden getrennt. Die Häufigkeit von Ausfällen hängt von der lokalen Infrastruktur oder der Zuverlässigkeit der ausgewählten Cloud ab. Auf jeden Fall müssen verteilte Systeme damit zurechtkommen. Wieder einmal haben wir die Wahl zwischen Verfügbarkeit und Konsistenz, und die gute Nachricht ist, dass RabbitMQ beide Optionen bietet (nur nicht gleichzeitig).

Mit RabbitMQ haben wir zwei Hauptoptionen:

  • Ermöglichen Sie eine logische Aufteilung (Split-Brain). Dies stellt die Verfügbarkeit sicher, kann jedoch zu Datenverlust führen.
  • Logische Trennung deaktivieren. Kann zu einem kurzfristigen Verlust der Verfügbarkeit führen, je nachdem, wie Clients eine Verbindung zum Cluster herstellen. Kann auch in einem Zwei-Knoten-Cluster zur völligen Nichtverfügbarkeit führen.

Aber was ist logische Trennung? Dies ist der Fall, wenn ein Cluster aufgrund des Verlusts von Netzwerkverbindungen in zwei Teile geteilt wird. Auf jeder Seite werden die Spiegel zu einem Meister befördert, so dass es schließlich mehrere Meister pro Spielzug gibt.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 17. Hauptwarteschlange und zwei Spiegel, jeweils auf einem separaten Knoten. Dann kommt es zu einem Netzwerkfehler und ein Spiegel wird getrennt. Der getrennte Knoten erkennt, dass die anderen beiden abgefallen sind und befördert seine Spiegel zum Master. Wir haben jetzt zwei Hauptwarteschlangen, sowohl beschreibbare als auch lesbare.

Wenn Herausgeber Daten an beide Master senden, erhalten wir am Ende zwei voneinander abweichende Kopien der Warteschlange.

Die verschiedenen Modi von RabbitMQ bieten entweder Verfügbarkeit oder Konsistenz.

Ignorieren-Modus (Standard)

Dieser Modus gewährleistet die Barrierefreiheit. Nach dem Verlust der Konnektivität erfolgt eine logische Trennung. Nachdem die Konnektivität wiederhergestellt ist, muss der Administrator entscheiden, welcher Partition Priorität eingeräumt werden soll. Die Verliererseite wird neu gestartet und alle auf dieser Seite gesammelten Daten gehen verloren.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 18. Drei Verleger sind mit drei Maklern verbunden. Intern leitet der Cluster alle Anfragen an die Hauptwarteschlange auf Broker 2 weiter.

Jetzt verlieren wir Broker 3. Er sieht, dass andere Broker abgefallen sind und befördert seinen Spiegel zum Meister. So kommt es zu einer logischen Trennung.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 19. Logische Teilung (Split-Brain). Datensätze gelangen in zwei Hauptwarteschlangen, und die beiden Kopien laufen auseinander.

Die Konnektivität wird wiederhergestellt, die logische Trennung bleibt jedoch bestehen. Der Administrator muss die Verliererseite manuell auswählen. Im folgenden Fall startet der Administrator Broker 3 neu. Alle Nachrichten, die er nicht übertragen konnte, gehen verloren.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 20. Der Administrator deaktiviert Broker 3.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 21. Der Administrator startet Broker 3 und dieser tritt dem Cluster bei, wobei alle dort hinterlassenen Nachrichten verloren gehen.

Während des Verbindungsverlusts und nach der Wiederherstellung standen der Cluster und diese Warteschlange zum Lesen und Schreiben zur Verfügung.

Autoheal-Modus

Funktioniert ähnlich wie der Ignorieren-Modus, außer dass der Cluster selbst nach der Aufteilung und Wiederherstellung der Konnektivität automatisch die Verliererseite auswählt. Die Verliererseite kehrt leer zum Cluster zurück und die Warteschlange verliert alle Nachrichten, die nur an diese Seite gesendet wurden.

Pausieren Sie den Minderheitenmodus

Wenn wir keine logische Partitionierung zulassen möchten, besteht unsere einzige Möglichkeit darin, Lese- und Schreibvorgänge auf der kleineren Seite nach der Clusterpartition zu verwerfen. Wenn der Broker feststellt, dass er auf der kleineren Seite ist, unterbricht er die Arbeit, d. h. er schließt alle bestehenden Verbindungen und lehnt alle neuen ab. Einmal pro Sekunde wird geprüft, ob die Konnektivität wiederhergestellt ist. Sobald die Konnektivität wiederhergestellt ist, nimmt es den Betrieb wieder auf und tritt dem Cluster bei.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 22. Drei Verleger sind mit drei Maklern verbunden. Intern leitet der Cluster alle Anfragen an die Hauptwarteschlange auf Broker 2 weiter.

Anschließend trennen sich die Broker 1 und 2 von Broker 3. Anstatt ihren Spiegel zum Master hochzustufen, wird Broker 3 angehalten und ist nicht mehr verfügbar.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 23. Broker 3 pausiert, trennt alle Clients und lehnt Verbindungsanfragen ab.

Sobald die Konnektivität wiederhergestellt ist, kehrt sie zum Cluster zurück.

Schauen wir uns ein weiteres Beispiel an, bei dem sich die Hauptwarteschlange auf Broker 3 befindet.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 24. Hauptwarteschlange auf Broker 3.

Dann tritt der gleiche Verbindungsverlust auf. Broker 3 pausiert, weil er auf der kleineren Seite ist. Auf der anderen Seite sehen die Knoten, dass Broker 3 ausgefallen ist, sodass der ältere Spiegel von Broker 1 und 2 zum Master befördert wird.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 25. Übergang zu Broker 2, wenn Broker 3 nicht verfügbar ist.

Wenn die Konnektivität wiederhergestellt ist, wird Broker 3 dem Cluster beitreten.

RabbitMQ vs. Kafka: Fehlertoleranz und hohe Verfügbarkeit in Clustern
Reis. 26. Der Cluster ist zum Normalbetrieb zurückgekehrt.

Hier ist es wichtig zu verstehen, dass wir Konsistenz erreichen, aber wir können auch Verfügbarkeit erreichen. wenn Wir werden Kunden erfolgreich in den größten Teil des Abschnitts vermitteln. Für die meisten Situationen würde ich persönlich den Pause Minority-Modus wählen, aber das hängt wirklich vom Einzelfall ab.

Um die Verfügbarkeit sicherzustellen, ist es wichtig sicherzustellen, dass Clients erfolgreich eine Verbindung zum Host herstellen. Schauen wir uns unsere Optionen an.

Sicherstellung der Kundenkonnektivität

Wir haben mehrere Möglichkeiten, Clients nach einem Verbindungsverlust zum Hauptteil des Clusters oder zu funktionierenden Knoten (nachdem ein Knoten ausgefallen ist) weiterzuleiten. Denken wir zunächst daran, dass eine bestimmte Warteschlange auf einem bestimmten Knoten gehostet wird, Routing und Richtlinien jedoch auf allen Knoten repliziert werden. Clients können sich mit jedem Knoten verbinden, und das interne Routing leitet sie dorthin, wo sie hin müssen. Wenn ein Knoten jedoch angehalten wird, lehnt er Verbindungen ab, sodass Clients eine Verbindung zu einem anderen Knoten herstellen müssen. Fällt der Knoten ab, kann er wenig tun.

Unsere Optionen:

  • Der Zugriff auf den Cluster erfolgt über einen Load Balancer, der einfach die Knoten durchläuft und die Clients erneut versuchen, eine Verbindung herzustellen, bis die Verbindung erfolgreich ist. Wenn ein Knoten ausgefallen oder angehalten ist, schlagen Versuche, eine Verbindung zu diesem Knoten herzustellen, fehl, nachfolgende Versuche werden jedoch an andere Server weitergeleitet (im Round-Robin-Verfahren). Dies eignet sich für einen kurzfristigen Verbindungsverlust oder einen ausgefallenen Server, der schnell wieder hochgefahren werden soll.
  • Greifen Sie über einen Load Balancer auf den Cluster zu und entfernen Sie angehaltene/ausgefallene Knoten aus der Liste, sobald sie erkannt werden. Wenn wir dies schnell tun und die Clients die Verbindung erneut versuchen können, erreichen wir eine ständige Verfügbarkeit.
  • Geben Sie jedem Client eine Liste aller Knoten, und der Client wählt beim Herstellen einer Verbindung zufällig einen davon aus. Wenn beim Versuch, eine Verbindung herzustellen, ein Fehler auftritt, wechselt es zum nächsten Knoten in der Liste, bis die Verbindung hergestellt wird.
  • Entfernen Sie den Datenverkehr von einem ausgefallenen/angehaltenen Knoten mithilfe von DNS. Dies geschieht mit einem kleinen TTL.

Befund

RabbitMQ-Clustering hat seine Vor- und Nachteile. Die gravierendsten Nachteile sind:

  • Beim Beitritt zu einem Cluster verwerfen Knoten ihre Daten.
  • Das Blockieren der Synchronisierung führt dazu, dass die Warteschlange nicht mehr verfügbar ist.

Alle schwierigen Entscheidungen ergeben sich aus diesen beiden architektonischen Merkmalen. Wenn RabbitMQ beim erneuten Beitritt zum Cluster Daten speichern könnte, wäre die Synchronisierung schneller. Wenn es eine nicht blockierende Synchronisierung ermöglichen würde, würde es große Warteschlangen besser unterstützen. Die Behebung dieser beiden Probleme würde die Leistung von RabbitMQ als fehlertolerante und hochverfügbare Messaging-Technologie erheblich verbessern. Ich würde RabbitMQ mit Clustering in den folgenden Situationen nur ungern empfehlen:

  • Unzuverlässiges Netzwerk.
  • Unzuverlässiger Speicher.
  • Sehr lange Warteschlangen.

Berücksichtigen Sie bei den Hochverfügbarkeitseinstellungen Folgendes:

  • ha-promote-on-failure=always
  • ha-sync-mode=manual
  • cluster_partition_handling=ignore (oder autoheal)
  • persistente Nachrichten
  • Stellen Sie sicher, dass Clients eine Verbindung zum aktiven Knoten herstellen, wenn ein Knoten ausfällt

Berücksichtigen Sie aus Gründen der Konsistenz (Datensicherheit) die folgenden Einstellungen:

  • Herausgeberbestätigungen und manuelle Bestätigungen auf Verbraucherseite
  • ha-promote-on-failure=when-synced, wenn die Herausgeber es später noch einmal versuchen können und wenn Sie über einen sehr zuverlässigen Speicher verfügen! Anders ausgedrückt =always.
  • ha-sync-mode=automatic (Für große inaktive Warteschlangen kann jedoch ein manueller Modus erforderlich sein. Bedenken Sie auch, ob die Nichtverfügbarkeit zum Verlust von Nachrichten führt.)
  • Pausieren Sie den Minderheitenmodus
  • persistente Nachrichten

Wir haben noch nicht alle Themen der Fehlertoleranz und Hochverfügbarkeit behandelt; zum Beispiel, wie man Verwaltungsvorgänge sicher durchführt (z. B. fortlaufende Updates). Wir müssen auch über Federation und das Shovel-Plugin sprechen.

Wenn ich noch etwas verpasst habe, lassen Sie es mich bitte wissen.

Siehe auch meine Post, wo ich mithilfe von Docker und Blockade Chaos auf einem RabbitMQ-Cluster anrichte, um einige der in diesem Artikel beschriebenen Nachrichtenverlustszenarien zu testen.

Vorherige Artikel in der Reihe:
Nr. 1 - habr.com/ru/company/itsumma/blog/416629
Nr. 2 - habr.com/ru/company/itsumma/blog/418389
Nr. 3 - habr.com/ru/company/itsumma/blog/437446

Source: habr.com

Kommentar hinzufügen