Unterschied zwischen Idempotenz und genau einmal in Kafka Stream

8

Ich habe das Dokument durchgearbeitet, von dem ich verstanden habe, dass wir mit Enabling genau einmal eine Transaktion erzielen können idempotence=true

idempotence: Der Idempotent-Produzent aktiviert genau einmal für einen Produzenten ein einzelnes Thema. Grundsätzlich hat jede einzelne gesendete Nachricht stärkere Garantien und wird im Fehlerfall nicht dupliziert

Wenn wir also bereits Idempotenz haben, warum brauchen wir dann genau einmal eine andere Eigenschaft in Kafka Stream? Was genau unterscheidet sich zwischen Idempotenz und genau einmal

Warum genau einmalige Eigenschaft nicht in normalen Kafka Producer verfügbar?

Sandeep
quelle
2
Dieser Blog-Beitrag ist auch eine gute Quelle für weitere Informationen: medium.com/@andy.bryant/…
Matthias J. Sax

Antworten:

6

In verteilten Umgebungen ist ein Ausfall ein sehr häufiges Szenario, das jederzeit auftreten kann. In einer Kafka-Umgebung kann der Broker abstürzen, ein Netzwerkfehler, ein Fehler bei der Verarbeitung, ein Fehler beim Veröffentlichen von Nachrichten oder ein Fehler beim Konsumieren von Nachrichten usw. Dieses unterschiedliche Szenario führte zu unterschiedlichen Arten von Datenverlust und -duplizierung.

Fehlerszenarien

A (Bestätigung fehlgeschlagen): Der Produzent hat die Nachricht erfolgreich mit einem Wiederholungsversuch> 1 veröffentlicht, konnte jedoch aufgrund eines Fehlers keine Bestätigung erhalten. In diesem Fall versucht der Produzent erneut, dass dieselbe Nachricht ein Duplikat enthält.

Geben Sie hier die Bildbeschreibung ein

B (Erzeugerprozess in Batch-Nachrichten fehlgeschlagen): Der Produzent hat einen Stapel von Nachrichten gesendet, die mit wenigen veröffentlichten Erfolgen fehlgeschlagen sind. In diesem Fall wird der Produzent nach dem Neustart erneut alle Nachrichten aus dem Stapel erneut veröffentlichen, wodurch ein Duplikat in Kafka eingeführt wird. Geben Sie hier die Bildbeschreibung ein

C (Fire & Forget Failed) Vom Produzenten veröffentlichte Nachricht mit Wiederholung = 0 (Feuer und Vergessen). Wenn ein veröffentlichter Fehler die nächste Nachricht nicht erkennt und sendet, geht die Nachricht verloren. Geben Sie hier die Bildbeschreibung ein

D (Verbraucher in Batch-Nachricht fehlgeschlagen) Ein Verbraucher empfängt einen Stapel von Nachrichten von Kafka und schreibt ihren Offset manuell fest (enable.auto.commit = false). Wenn der Verbraucher vor der Verpflichtung gegenüber Kafka versagt hat, wird der Verbraucher beim nächsten Mal wieder dieselben Datensätze verwenden, die auf der Verbraucherseite ein Duplikat reproduzieren.

Geben Sie hier die Bildbeschreibung ein

Genau einmalige Semantik

Selbst wenn ein Produzent versucht, eine Nachricht erneut zu senden, führt dies in diesem Fall dazu, dass die Nachricht genau einmal veröffentlicht und vom Verbraucher konsumiert wird.

Um in Kafka eine genau einmalige Semantik zu erreichen, werden weniger als 3 Eigenschaften verwendet

  1. enable.idempotence = true (Adresse a, b & c)
  2. MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION = 5 (Der Produzent hat immer eine Anforderung während des Fluges pro Verbindung)
  3. isolation.level = read_committed (Adresse d)

Idempotent aktivieren (enable.idempotence = true)

Durch die unzulässige Zustellung kann der Hersteller während der Lebensdauer eines einzelnen Herstellers ohne Datenverlust und Bestellung pro Partition genau einmal eine Nachricht an Kafka an eine bestimmte Partition eines Themas schreiben.

"Beachten Sie, dass zum Aktivieren der Idempotenz MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION kleiner oder gleich 5 sein muss, RETRIES_CONFIG größer als 0 und ACKS_CONFIG 'all' sein muss. Wenn diese Werte nicht explizit vom Benutzer festgelegt werden, werden geeignete Werte ausgewählt. Wenn inkompatible Werte sind gesetzt, wird eine ConfigException ausgelöst "

Um Idempotenz zu erreichen, verwendet Kafka eine eindeutige ID, die als Produkt-ID oder PID und Sequenznummer bezeichnet wird, während Nachrichten erstellt werden. Der Produzent erhöht die Sequenznummer für jede veröffentlichte Nachricht, die eine eindeutige PID aufweist. Der Broker vergleicht immer die aktuelle Sequenznummer mit der vorherigen und lehnt ab, wenn die neue nicht +1 größer als die vorherige ist, wodurch Duplikate vermieden werden, und gleichzeitig, wenn mehr als eine größere Show in Nachrichten verloren geht Geben Sie hier die Bildbeschreibung ein

Im Fehlerszenario vergleicht der Broker die Sequenznummer mit der vorherigen und wenn die Sequenz nicht erhöht wird, lehnt +1 die Nachricht ab. Geben Sie hier die Bildbeschreibung ein

Transaktion (Isolationsstufe)

Transaktionen geben uns die Möglichkeit, Daten in mehreren Themenpartitionen atomar zu aktualisieren. Alle in einer Transaktion enthaltenen Datensätze werden erfolgreich gespeichert, oder keiner von ihnen wird erfolgreich gespeichert. Auf diese Weise können Sie Ihre Consumer-Offsets zusammen mit den von Ihnen verarbeiteten Daten in derselben Transaktion festschreiben und so eine durchgängige Semantik genau einmal zulassen .

Der Produzent wartet nicht darauf, eine Nachricht an kafka zu schreiben, in der der Produzent beginTransaction, commitTransaction und abortTransaction verwendet (im Fehlerfall). Der Consumer verwendet isolation.level, entweder read_committed oder read_uncommitted

  • read_committed: Der Verbraucher liest immer nur festgeschriebene Daten.
  • read_uncommitted: Liest alle Nachrichten in versetzter Reihenfolge, ohne darauf zu warten, dass Transaktionen festgeschrieben werden

Wenn ein Verbraucher mit isolation.level = read_committed eine Kontrollnachricht für eine Transaktion erreicht, die nicht abgeschlossen wurde, werden keine weiteren Nachrichten von dieser Partition übermittelt, bis der Produzent die Transaktion festschreibt oder abbricht oder ein Transaktionszeitlimit auftritt. Das Transaktionszeitlimit wird vom Hersteller mithilfe der Konfiguration transaction.timeout.ms (Standard 1 Minute) festgelegt.

Genau einmal bei Produzent & Konsument

In normalem Zustand, wo wir getrennte Produzenten und Konsumenten haben. Der Produzent muss idempotent sein und gleichzeitig die Transaktion verwalten, damit der Konsument Isolation.level verwenden kann, um nur read_committed zu lesen und den gesamten Prozess als atomare Operation auszuführen. Dies garantiert, dass der Produzent immer mit dem Quellsystem synchronisiert wird. Selbst wenn ein Absturz des Produzenten oder eine Transaktion abgebrochen wird, ist dies immer konsistent und veröffentlicht eine Nachricht oder einen Stapel von Nachrichten einmal als Einheit.

Derselbe Verbraucher erhält entweder einmal eine Nachricht oder einen Nachrichtenstapel als Einheit.

In Exactly-Once wird der semantische Produzent zusammen mit dem Verbraucher als atomare Operation erscheinen, die als eine Einheit arbeiten wird. Entweder veröffentlichen und einmal verbrauchen oder abgebrochen werden.

Genau einmal im Kafka Stream

Kafka Stream verwendet Nachrichten aus Thema A, verarbeitet und veröffentlicht Nachrichten in Thema B und verwendet nach der Veröffentlichung Commit (Commit wird meistens unter Deckung ausgeführt), um alle Statusspeicherdaten auf die Festplatte zu leeren.

Genau einmal in Kafka Stream gibt es ein Lese-Prozess-Schreibmuster, das garantiert, dass diese Operation als atomare Operation behandelt wird. Da Kafka Stream Hersteller, Verbraucher und Transaktion zusammen versorgt, bietet Kafka Stream eine spezielle Parameterverarbeitung. Garantie, die genau einmal oder mindestens einmal verfügbar sein kann und es dem Leben leicht macht, nicht alle Parameter separat zu behandeln.

Kafka Streams aktualisiert Verbraucher-Offsets, lokale State Stores, State Store Changelog-Themen und Produktion atomar, um Themen zusammen auszugeben. Wenn einer dieser Schritte fehlschlägt, werden alle Änderungen rückgängig gemacht.

process.guarantee: sure_once liefert automatisch die folgenden Parameter, die Sie nicht explizit festlegen müssen

  1. isolation.level = read_committed
  2. enable.idempotence = true
  3. MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION = 5
sun007
quelle
12

Kafka Stream bietet die genau einmalige Semantik von Ende zu Ende (verbraucht von einem Thema, verarbeitet diese Nachricht und produziert dann zu einem anderen Thema). Sie haben jedoch nur das idempotente Attribut des Produzenten erwähnt . Das ist nur ein kleiner Teil des Gesamtbildes.

Lassen Sie mich die Frage umformulieren:

Warum brauchen wir die genau einmalige Liefersemantik auf der Verbraucherseite, während wir die genau einmalige Liefersemantik auf der Herstellerseite bereits garantiert haben?

Antwort: Da sich die genau einmalige Liefersemantik nicht nur im Produktionsschritt befindet, sondern im gesamten Verarbeitungsfluss. Um die genau einmalige Lieferung semantisch zu erreichen, müssen einige Bedingungen beim Produzieren und Konsumieren erfüllt sein.

Dies ist das generische Szenario: Prozess A erzeugt Nachrichten zum Thema T. Gleichzeitig versucht Prozess B, Nachrichten aus dem Thema T zu konsumieren. Wir möchten sicherstellen, dass Prozess B niemals eine Nachricht zweimal verarbeitet.

Produzententeil: Wir müssen sicherstellen, dass Produzenten niemals zweimal eine Nachricht produzieren. Wir können Kafka Idempotent Producer verwenden

Verbraucherteil: Hier ist der grundlegende Workflow für den Verbraucher:

  • Schritt 1: Der Verbraucher zieht die Nachricht M erfolgreich aus dem Kafka-Thema.
  • Schritt 2: Der Verbraucher versucht, den Job auszuführen, und der Job wird erfolgreich zurückgegeben.
  • Schritt 3: Der Verbraucher schreibt den Versatz der Nachricht an die Kafka-Broker.

Die obigen Schritte sind nur ein glücklicher Weg. In der Realität treten viele Probleme auf.

  • Szenario 1: Der Job in Schritt 2 wird erfolgreich ausgeführt, aber dann stürzt der Consumer ab. Seit diesem unerwarteten Umstand hat der Verbraucher den Versatz der Nachricht noch nicht festgeschrieben. Beim Neustart des Verbrauchers wird die Nachricht zweimal verwendet.
  • Szenario 2: Während der Consumer den Offset in Schritt 3 festschreibt, stürzt er aufgrund von Hardwarefehlern ab (z. B. CPU, Speicherverletzung, ...). Beim Neustart kann der Consumer nicht feststellen, ob er den Offset erfolgreich festgeschrieben hat oder nicht.

Da möglicherweise viele Probleme auftreten, müssen die Ausführung des Jobs und der Festschreibungsoffset atomar sein , um auf Verbraucherseite eine genau einmalige Lieferungssemantik zu gewährleisten. Das bedeutet nicht, dass wir es nicht können, aber es erfordert viel Aufwand, um sicherzustellen, dass die Semantik genau einmal geliefert wird. Kafka Stream unterstützt die Arbeit der Ingenieure.

Beachten Sie: Kafka Stream bietet "genau einmalige Stream-Verarbeitung". Es bezieht sich auf das Konsumieren aus einem Thema, das Materialisieren des Zwischenzustands in einem Kafka-Thema und das Produzieren zu einem. Wenn unsere Anwendung von anderen externen Diensten abhängt (Datenbank, Dienste ...), müssen wir sicherstellen, dass unsere externen Abhängigkeiten in diesen Fällen genau einmal garantieren können.

TL, DR: Genau einmal für den vollen Fluss braucht die Zusammenarbeit zwischen Produzenten und Konsumenten.

Verweise:

hqt
quelle
Ich würde es nicht als Zustellung bezeichnen , da die Zustellung normalerweise impliziert, wie oft eine Nachricht gelesen / gesendet wird und genau einmal in Kafka offensichtlich intern aufgrund eines Fehlers in den Ruhestand geht. Eine genau einmalige Zustellung (dh wie oft eine Nachricht tatsächlich über das Netzwerk gesendet wird) ist nachweislich nicht möglich (vgl. En.wikipedia.org/wiki/Byzantine_fault und en.wikipedia.org/wiki/Two_Generals%27_Problem )
Matthias J. Sax
Ja. Wie in der Antwort erwähnt, bietet Kafka Stream im Allgemeinen keine genau einmalige Lieferung an. Über zwei allgemeine Probleme können wir im verteilten System nicht genau einmal allgemein haben, aber es ist machbar, wenn wir einige Bedingungen verlieren oder dem System weitere Bedingungen hinzufügen. zB: Timeout. Dies ist jedoch die andere Geschichte.
Hqt
Nun, ich würde den Begriff Lieferung einfach nicht verwenden , sondern mich an die Semantik halten .
Matthias J. Sax