Die Architektur des verteilten Nachrichtenwarteschlangendienstes in Yandex.Cloud

Hallo, ich heiße Vasily Bogonatov. Ich bin einer von denen, die meine Hand und meinen Kopf legen und meine Seele in den Dienst verteilter persistenter Nachrichtenwarteschlangen der Yandex Message Queue stellen. Der Dienst ging Ende Mai an die Börse, wurde jedoch in Yandex seit langem aktiv in verschiedenen Produkten eingesetzt.

Heute möchte ich Habrs Lesern von Nachrichtenwarteschlangen im Allgemeinen und von Yandex Message Queue im Besonderen erzählen. Zunächst möchte ich erklären, was eine "verteilte Warteschlange für persistente Nachrichten" ist und warum sie benötigt wird. Zeigen Sie den praktischen Wert, die Mechanik der Arbeit mit Nachrichten, sprechen Sie über die API und die Benutzerfreundlichkeit. In der zweiten Hälfte des Artikels werden wir uns mit der technischen Seite befassen: Wie wird die Yandex-Datenbank in unseren Warteschlangen verwendet (dies ist eine zuverlässige Grundlage unseres Service), wie sieht ein naiver und verbesserter Ansatz zum Erstellen einer Architektur aus, welche Probleme werden durch die Verteilung verursacht und wie können sie gelöst werden.



Was ist eine verteilte Warteschlange für persistente Nachrichten?


Wikipedia definiert die Nachrichtenwarteschlange als "Software-Engineering-Komponente, die für die Interprozess- oder Inter-Thread-Interaktion innerhalb eines Prozesses verwendet wird". Tatsächlich ist dieses Konzept etwas umfassender: Prozesse, die über eine Warteschlange interagieren, können sich auf verschiedenen Servern und sogar in verschiedenen Rechenzentren befinden.

Wir werden die Begriffe etwas klären.

Eine Nachrichtenwarteschlange ist ein Repository, das das Platzieren und Lesen von Daten in einer bestimmten Reihenfolge ermöglicht.

Zwei Arten von Entitäten interagieren normalerweise mit einer Warteschlange:

  • Autoren (Produzenten) - Nachrichten an die Warteschlange senden;
  • Leser (Verbraucher) - Empfangen (Lesen) von Nachrichten aus der Warteschlange.

Bei Verwendung der Warteschlange sind Leser und Schreiber unabhängig voneinander. Sie können mit unterschiedlicher Leistung, Zuverlässigkeit und Verfügbarkeit arbeiten und können sogar in verschiedenen Programmiersprachen geschrieben werden.

Das Hauptszenario für die Warteschlange: Nachrichten vom Schreiber zuverlässig und schnell an den Leser übertragen. Im Gegensatz zur Datenbank ist die Warteschlange nicht für die Langzeitspeicherung von Nachrichten vorgesehen. In vielen gängigen Implementierungen gibt es einen entsprechenden Parameter - "Nachrichtenaufbewahrungszeitraum". Es bestimmt, wie lange die Nachricht gespeichert wird, bis sie dauerhaft gelöscht wird.

Wir haben das Konzept der Warteschlange herausgefunden, gehen zu "Verteilung" und "Persistenz".

  • Verteilung bedeutet in unserem Fall das Vorhandensein eines Clusters, der Daten und Warteschlangenmetadaten speichert und verarbeitet und alle seine Knoten mithilfe eines Computernetzwerks zu einem Ganzen zusammenfasst.
  • Persistenz bedeutet, dass alle Nachrichten in der Warteschlange auf die Festplatte geschrieben werden und der Schreiber erst nach erfolgreicher Aufzeichnung eine Bestätigung des Sendens erhält.

Verteilung und Persistenz wirken sich nicht auf die Hauptfunktionalität der Warteschlange aus, sondern bieten Fehlertoleranz und Zuverlässigkeit der Datenspeicherung. Welche Arten von Fehlern in unserem System auftreten können, werden wir etwas später prüfen. Ich kann mir jedoch das Vergnügen nicht verweigern und die Karten ein wenig öffnen: In der gesamten Geschichte der Existenz des Dienstes haben wir keine einzige gespeicherte Nachricht vom Kunden verloren.

Wofür ist die Nachrichtenwarteschlange?


Die Warteschlange ermöglicht es Ihnen, die logisch unabhängigen Teile von Diensten voneinander zu trennen, dh sie bietet eine Entkopplung , die in den heute gängigen Mikrodiensten so gefragt ist. Dies erhöht die Skalierbarkeit und Zuverlässigkeit: Sie können jederzeit den Datenstrom in der Warteschlange erhöhen und mehr Leser hinzufügen - Nachrichtenhandler, während der Ausfall von Lesern die Arbeit der Autoren nicht beeinträchtigt.

Warteschlangen glätten Spitzenlasten: Sie dienen als Puffer für Leser. Wenn die aktuellen Leserkapazitäten nicht für die sofortige Verarbeitung aller eingehenden Nachrichten ausreichen, werden die Nachrichten in der Warteschlange später verarbeitet, wenn die Last abnimmt. Das Puffern ist nützlich für Dienste mit einer instabilen Last, bei denen keine sofort eingehenden Ereignisse erforderlich sind.

Lassen Sie uns am Beispiel eines Suchroboters (schließlich hat Yandex mit einer Suche begonnen!) Sehen, wie Webseiten heruntergeladen, verarbeitet und in eine Datenbank gestellt werden. Nehmen wir eine solche Architektur.



Die Nachrichtenwarteschlange löst hier die folgenden Probleme:

  1. Der Roboter arbeitet viel schneller als die Mitarbeiter, die für das Parsen und Laden von Seiten in die Datenbank verantwortlich sind. Außerhalb der Linie würden sich Links ansammeln und den verfügbaren Speicher oder die verfügbare Festplatte füllen. Das gleiche würde passieren, wenn die Arbeiter vorübergehend nicht verfügbar wären.
  2. Ohne Warteschlange muss der Roboter die Arbeitsoberfläche der Mitarbeiter „kennen“, um ihnen Aufgaben zuweisen zu können. Die Benutzeroberfläche kann sich während der Produktentwicklung ändern.
  3. Ein einzelner Mitarbeiter hat eine relativ geringe Zuverlässigkeit, daher gibt es keine Garantie dafür, dass die übertragene Verbindung von ihm vollständig verarbeitet wird.

Die Warteschlange bietet zuverlässige Datenspeicherung mit Skalierung und ermöglicht es Ihnen, die Verarbeitung von Links zu verzögern. Wenn ein Mitarbeiter ausfällt, wird die unformatierte Verknüpfung nach einer bestimmten Zeit zur Verarbeitung durch einen anderen Mitarbeiter in die Warteschlange zurückgeführt. Die Warteschlange verfügt über eine eigene Schnittstelle, die in der Dokumentation getestet und beschrieben wird, sodass Suchroboter- und Arbeitersysteme unterschiedliche Teams in unterschiedlichen Programmiersprachen entwickeln können. Dies hat keinen Einfluss auf die Gesamtleistung.

Funktionsweise der Yandex Message Queue mit Nachrichten


Hier können drei Hauptstufen unterschieden werden:

  • Schreiben einer Nachricht in die Warteschlange;
  • Lesen einer Nachricht aus der Warteschlange;
  • Entfernen einer Nachricht aus der Warteschlange.

Ein Datensatz gilt als erfolgreich, wenn die Nachricht sicher gespeichert wurde und den Lesern bald zur Verfügung steht. Eine Deduplizierungsaufzeichnung ist möglich: Wenn ein wiederholter Versuch, eine gesendete Nachricht aufzuzeichnen, ignoriert wird.

Zum Zeitpunkt des Lesens wird die Nachricht für einen Zeitraum, der als Sichtbarkeitszeitlimit bezeichnet wird, aus der Warteschlange ausgeblendet und ist für andere Leser nicht mehr zugänglich. Wenn das Sichtbarkeitszeitlimit abläuft, kehrt die Nachricht in die Warteschlange zurück und steht wieder zur Verarbeitung zur Verfügung. Die Reihenfolge, in der Nachrichten gelesen werden, wird von der Warteschlange und nicht vom Leser bestimmt.

Der Leser selbst und die Netzwerkverbindung mit ihm sind möglicherweise unzuverlässig. Ein Sichtbarkeitszeitlimit ist erforderlich, um eine Nachricht an die Warteschlange zurückgeben zu können, wenn der Reader abstürzt oder die Verbindung getrennt wird. Andernfalls ist es wahrscheinlich, dass eine einzelne Nachricht niemals korrekt verarbeitet wird.

Nach erfolgreichem Lesen wird die Nachricht mit der Kennung ReceiptHandle an den Client übertragen. Ein Bezeichner gibt bestimmte Daten an, die aus der Nachrichtenwarteschlange entfernt werden sollen.

Warteschlangentypen in der Yandex-Nachrichtenwarteschlange


Der erste und am häufigsten verwendete Typ ist die Standardwarteschlange. Es zeichnet sich durch einen hohen Durchsatz (Tausende von Nachrichten pro Sekunde), eine hervorragende Leistung und eine kurze Ausführungszeit für grundlegende Vorgänge aus. Standardwarteschlangen bestehen aus logischen Shards und unterstützen eine nahezu lineare Bandbreitenskalierung.


Standardwarteschlangen unterstützen keine Deduplizierung von Nachrichten beim Schreiben in eine Warteschlange und garantieren keine Lesereihenfolge. Aufgrund der Verwendung von Sharding gibt eine Leseanforderung möglicherweise keine einzelne Nachricht zurück, selbst wenn sie sich in der Warteschlange befindet. Meistens geschieht dies im Kurzabfragemodus , wenn das Lesen von einem zufällig ausgewählten Shard stammt.

Der zweite Typ - FIFO - ist das Gegenteil der Standardwarteschlange. Es bietet eine strikte Lesereihenfolge, unterstützt die Deduplizierung beim Schreiben und wiederholte Versuche, Nachrichten zu lesen. Leistung und Skalierbarkeit sind niedriger als Standard. Die Leistung der FIFO-Warteschlange ist auf 30 Anforderungen pro Sekunde begrenzt. Es wird empfohlen, FIFO zu verwenden, wenn Sie versuchen müssen, die Übermittlungssemantik „genau einmal“ sicherzustellen. Normalerweise bedeutet das Wort "Warteschlange" FIFO.


Yandex Message Queue API


API ist ein äußerst wichtiger Bestandteil jedes Produkts. Eine gute Softwareschnittstelle sollte einfach und unkompliziert sein und für eine effektive Verwendung nur minimale Kenntnisse der Dokumentation erfordern. Sollte es nicht zulassen, seltsame oder unnötige Handlungen durchzuführen und sich vor dummen Fehlern zu schützen, sollte die Verletzung des „Vertrags“ rechtzeitig gemeldet werden.

Wenn das System über eine solche API verfügt, empfängt es schnell treue Benutzer und ist von praktischen „Wrappern“ für verschiedene Plattformen und Programmiersprachen umgeben.

Die Amazon Simple Queue Service-API (AWS SQS-API) ist ein Beispiel für eine solche Schnittstelle, die nach Zeit und einer großen Anzahl von Clients getestet wurde. Aus diesem Grund haben wir beschlossen, keine eindeutige Schnittstelle für die Yandex Message Queue zu erfinden, sondern die Unterstützung für die AWS SQS-API sehr sorgfältig implementiert.

In den meisten Fällen reicht es für den SQS-Benutzer aus, den Endpunkt (Dienstadresse) und die Region zu ändern (derzeit verwenden wir nur "ru-central1") und neue Anmeldeinformationen in Yandex.Cloud abzurufen. Alles andere, z. B. ein Skript, das die AWS-Befehlszeile verwendet , Code, der das AWS SDK verwendet, oder ein vorgefertigter Dienst für Sellerie oder Boto , wird höchstwahrscheinlich nicht berührt. Die Logik und Funktionalität des Warteschlangendienstes bleiben unverändert.


Eine ausführliche Beschreibung der Yandex Message Queue-API-Methoden finden Sie in der Servicedokumentation .

Ein wenig über Bequemlichkeit


Yandex Message Queue ist ein verwalteter Dienst, dh Yandex. Die Cloud ist für den Betrieb von Servern und Software verantwortlich. Das Serviceteam überwacht den Zustand der Warteschlangen, ersetzt ausgefallene Festplatten schnell, beseitigt Netzwerkunterbrechungen und führt Aktualisierungen durch. Das Update beendet den Dienst nicht: Während wir die neue Version von YMQ auf einer Gruppe von Servern installieren, leitet der Load Balancer den Datenverkehr sorgfältig an andere weiter. Benutzer bemerken also nichts.

Um Ihnen die Steuerung des Betriebs der Warteschlangen zu erleichtern, haben wir YMQ eine große Anzahl visueller Diagramme hinzugefügt. Nur ein kleiner Teil davon wird hier angezeigt. Diagramme befinden sich in der Yandex.Cloud-Konsole im Abschnitt "Statistik".


Wir werden Sie über die vier unserer Meinung nach nützlichsten Grafiken informieren:

  • Mit dem Diagramm „Nachrichten in der Warteschlange “ können Sie die Ansammlung von Daten in der Warteschlange überwachen. Ein Wachstum im Diagramm kann bedeuten, dass die Handler die Last nicht verwalten oder die Verarbeitung gestoppt wurde.
  • Grafik "Alter der ältesten Nachricht in der Warteschlange" : Große Werte weisen auf Probleme bei der Nachrichtenverarbeitung hin. Wenn alles richtig funktioniert, sollten Nachrichten nicht lange in der Warteschlange stehen.
  • Die Grafik „Anzahl der Leseversuche einer Nachricht“ zeigt, wann Nachrichten mehrmals gelesen werden. Dies kann bedeuten, dass die Handler abstürzen, wenn sie einige Nachrichten empfangen.
  • Das Diagramm "Warteschlangenzeit" gibt an, wie viel Zeit vom Senden der Nachricht an die Warteschlange bis zum Empfang durch den Handler vergeht.

Mithilfe von Diagrammen können Sie die Dynamik der Warteschlange und das Vorhandensein von Fehlern sofort bewerten, ohne dass Protokolle angezeigt werden müssen.

Wir haben mehr oder weniger allgemeine Punkte besprochen. Kommen wir nun zu den Details.

Wie die Yandex-Datenbankwarteschlange die Yandex-Datenbank verwendet


Der Yandex Message Queue-Dienst basiert auf der geoverteilten fehlertoleranten Yandex Database (YDB) -Datenbank , die strikte Konsistenz und Unterstützung für ACID-Transaktionen bietet. Wir werden das Gerät und die Eigenschaften jetzt nicht zerlegen, sondern uns auf das allgemeine Schema beschränken.


Eine Warteschlange in YMQ besteht aus logischen Shards, die durch einen festen Satz von YDB-Tabellen dargestellt werden. Jede Tabelle speichert ihre eigenen Informationen. Beispielsweise gibt es eine allgemeine Statustabelle namens State, in der Offs und die tatsächliche Anzahl von Nachrichten gespeichert sind. Es gibt eine Tabelle mit Daten- und Nachrichtenmetadaten. Es gibt eine Tabelle mit verwandten Attributen.

Alle Hauptoperationen mit der Warteschlange - Arbeiten mit Nachrichten, Ändern von Attributen, Erstellen und Löschen - funktionieren mit der Hierarchie von Tabellen und YDB-Verzeichnissen oder mit Transaktionsabfragen an eine oder mehrere Tabellen der Warteschlange. Die Daten in den Warteschlangentabellen sind die Quelle der absoluten Wahrheit. Daher ist es neben dem korrekten und stabilen Betrieb der Datenbank erforderlich, eine zuverlässige Speicherung und eine hohe Datenverfügbarkeit sicherzustellen.

Unsere Informationen werden in mehreren Replikaten gespeichert: eine Kopie in jedem der drei Yandex-Rechenzentren. Wenn eines der Rechenzentren nicht verfügbar ist, verdoppelt sich die Anzahl der Replikate in den verbleibenden. Somit wird das erforderliche Maß an Zuverlässigkeit wiederhergestellt. Selbst wenn ein gesamtes Rechenzentrum und ein Service Desk in einem anderen ausfallen, sind die Daten vollständig zugänglich.

Die erste Version der Yandex Message Queue-Architektur


So sah die erste Version der YMQ-Architektur aus, die wir selbst als naiv bezeichneten.


Das Diagramm zeigt den Pfad der HTTPS-Anforderung vom YMQ-Client zum YDB-Repository. Schauen wir uns die Hauptkomponenten an:

  1. Der L3-Balancer sendet eine Anfrage an das Yandex-Rechenzentrum, das dem Benutzer am nächsten liegt. Dies reduziert die Netzwerklatenz, obwohl die Last ungleichmäßig verteilt ist.
  2. Nginx auf der virtuellen Yandex.Cloud-Maschine beendet HTTPS-Verbindungen, bietet Schutz vor Netzwerkangriffen und leitet die Anforderung weiter an den YMQ-Server weiter, der sich bereits in HTTP befindet.
  3. Der YMQ-HTTP-Server implementiert die SQS-HTTP-API-Logik, validiert die Anforderung und übersetzt sie in ein stark typisiertes Protobuf-Format.
  4. YMQ Akteursystem - Akteursystem . Gleichzeitig wurden Tausende verschiedener Akteure ins Leben gerufen, die Informationen austauschen. Das Akteursystem jedes Hosts ist Teil eines Clusters. Alle Akteure im Cluster leben und agieren als Ganzes. Die YMQ-Geschäftslogik ist in verschiedenen Akteuren implementiert, die an Transaktionsanforderungen an YDB beteiligt sind.
  5. YDB-Tablets ("Tablets") - Teil der Kern-YDB, die für die Arbeit mit Tabellen in Abfragen und Transaktionen verantwortlich ist. Die Tablets selbst speichern keine Daten. Dies sind Kontrollstrukturen im Speicher, die bei einem Hardwarefehler den Status wiederherstellen können.
  6. Speicher ist ein zuverlässiger, verteilter und fehlertoleranter Speicher.

Diese Architektur hat einen Nachteil: Alle Server im Cluster arbeiten unabhängig voneinander mit Tabellen derselben Warteschlange. Dies wirkt sich negativ auf die Leistung aus und verhindert die Organisation zuverlässiger Caches für versteckte und lesbare Nachrichten. Es ist schwierig, den Anforderungsfluss zu begrenzen, und dies ist für jeden hoch ausgelasteten Dienst sehr wichtig.

Yandex Message Queue-Architektur mit Warteschlangenmastern


Das Auslösen von Lasten zeigte, dass die erste Version der Architektur mit einem Shard etwa 450 Nachrichten pro Sekunde und Warteschlange standhält. Es war sehr klein.
Das Hauptproblem waren Streitfragen. Eine große Anzahl logisch widersprüchlicher Transaktionen brachte versteckte Nachrichten-Caches schnell in einen inkonsistenten Zustand. Um das Problem zu lösen, haben wir eine spezielle Entität eingeführt - den Warteschlangenmaster.


Ein Warteschlangenmaster ist ein Akteur, der unter normalen Bedingungen in einem Cluster in einer einzelnen Instanz vorhanden ist und alle Anforderungen durchläuft, die einer bestimmten Warteschlange zugeordnet sind. Wenn eine Anforderung an die Warteschlange bei einem Server ankommt, auf dem der gewünschte Master fehlt, leitet ein spezieller Proxy-Akteur die Anforderung um und übersetzt dann die vom Master empfangene Antwort zurück.

Bei Verwendung des Warteschlangenassistenten reduziert der korrekte Cache entsperrter Nachrichten die Konflikte bei der Arbeit mit Tabellen. Die Implementierung der Einschränkung des Anforderungsflusses wird beispielsweise durch den Leaky-Bucket vereinfacht. Es stehen schnelle und genaue Warteschlangenmetriken zur Verfügung: Anzahl der Nachrichten, Gesamtverkehr und dergleichen. Sie können ähnliche Anforderungen gruppieren.

Theoretisch hat eine solche Architektur bestimmte Nachteile, die mit der Zentralisierung verbunden sind:

  1. Reduzieren der Fehlertoleranz: Wenn eine virtuelle Maschine mit einem Master ausfällt, sind alle Warteschlangen mit Master nicht verfügbar. Mit den speziellen Mechanismen von YDB können Sie jedoch innerhalb weniger Sekunden neue Master innerhalb des Clusters erstellen. Dies löst das Problem weitgehend.
  2. Eingeschränkte Skalierbarkeit: Alle Anforderungen werden über einen Host gesendet. Der Nachteil sind ebene YDB-Tabletten. Sie machen die ganze harte Arbeit mit den Daten. Der Master sendet asynchron Anforderungen und verarbeitet die empfangenen Ergebnisse. Dies macht es zu einer „leichten“ Einheit, die beim Stresstest keinen „Engpass“ -Effekt erzeugt.

Warteschlange des Abfrage-Assistenten


Verteilte Transaktionen mit Datenbanktabellen führen zu bestimmten zusätzlichen Kosten, sodass die Idee, die Anzahl der Abfragen zu reduzieren, für uns logisch erschien. Einhundert Transaktionen zum Aufzeichnen von Nachrichten nacheinander lassen sich besser in eine Transaktion zum gleichzeitigen Aufzeichnen von hundert Nachrichten umwandeln. Mit Warteschlangenmastern ist die Implementierung einer solchen Stapelverarbeitung (Stapelverarbeitung) viel einfacher.


Durch das Stapeln wird die Latenz während des Betriebs geringfügig erhöht. Stattdessen wird die Bandbreite erheblich erhöht. Beim Batching kann eine Single-Shard-Warteschlange bis zu 30.000 Anforderungen pro Sekunde verarbeiten.

Im Allgemeinen kann das Laden von Warteschlangen sehr unterschiedlich sein: Tausende von Nachrichten pro Sekunde und mehrere Nachrichten pro Tag. Wir mussten die Arbeit mit Warteschlangen mithilfe eines flexiblen Algorithmus optimieren. Frontaloptionen mit der Anhäufung von Nachrichten im Puffer auf die Schwellennummer oder einem Timer-Reset passten nicht zu uns. Aus diesem Grund haben wir einen adaptiven Batching-Algorithmus für YMQ entwickelt, der in beiden Fällen gut funktioniert. Seine Arbeiten werden im Zeitdiagrammformat gezeigt.


Wenn eine neue Nachricht eintrifft, ist hier eines von drei Szenarien möglich:

  1. Eine Transaktion wird sofort gestartet, wenn keine anderen Transaktionen dieses Typs ausgeführt werden.
  2. Wenn bereits Transaktionen ausgeführt werden, wird die Nachricht zum Puffer hinzugefügt und wartet auf den Abschluss der Transaktionen.
  3. Wenn die Puffergröße den Schwellenwert überschreitet, wird eine weitere parallele Transaktion gestartet. Die Anzahl der gleichzeitigen Transaktionen ist begrenzt.

Die Idee des adaptiven Batchings ähnelt dem Nagle-Algorithmus für TCP / IP. : , latency . , . .


Yandex Message Queue, , . , , -.

YDB . YMQ .

, , , .


YMQ . . «» .


YDB . , , , «». , . .


: . , «» . -, «» , «», .

« » . , , .

Yandex Message Queue


Yandex Message Queue – - . . , . .

  • - , , . .
  • API , . , .
  • , : , . , . . boto, 24/7, - .
  • , , . .

. - . . .

:

  • 5, ;
  • YDB;
  • , , , ;
  • , ;
  • . .

.

Abschließend


– , , , . ., ., ., . .

. . , Yandex Message Queue .

Source: https://habr.com/ru/post/de455642/


All Articles