Ordnung gilt je Schlüssel
Ein Log wie Kafka teilt einen Strom in Partitionen. Innerhalb einer Partition gilt die Reihenfolge, in der Ereignisse angehängt wurden; über Partitionen hinweg gibt es keine. Welche Ereignisse geordnet bleiben, bestimmt darum der Schlüssel. Der Sender setzt als Schlüssel die Identität des Objekts, und alle Ereignisse eines Objekts landen in derselben Partition. Mehr Ordnung braucht die Ontologie nicht, und mehr bietet ein verteiltes Log nicht ohne Engpass.
Die Zuordnung von Schlüssel zu Partition hängt von der Zahl der Partitionen ab. Wer sie später erhöht, ändert die Zuordnung; Ereignisse desselben Objekts können dann in zwei Partitionen liegen, alte und neue. FORGE legt die Zahl beim Anbinden mit Reserve fest und behandelt eine Änderung wie eine Migration: neuer Strom, Übergang, Umschalten.
Jedes Ereignis trägt zwei Zeiten, die Ereigniszeit, wann es in der Welt geschah, und die Aufnahmezeit, wann FORGE es annahm. In der Ontologie wird die Ereigniszeit zur Gültigkeitszeit und die Aufnahmezeit zur Erfassungszeit. Die Reihenfolge im Log bestimmt, in welcher Folge Ereignisse eines Schlüssels angewandt werden.
Strom im Schnitt
Unten die Quelle, darüber das Log mit Partitionen je Schlüssel. Die Verarbeitung hält Fenster und Zustand, die Ontologie nimmt Aussagen in der Reihenfolge je Objekt an.
- Ontologie (je Objekt geordnet): Aussage.
- Verarbeitung (mit Zustand): Fenster, Zustand.
- Log (Partition je Schlüssel): Partition, Offset.
- Quelle (Ereignisse): Sensorik, Ereignis.
- liest: fließt von quelle nach ontologie.
Doppel erkennen
Zustellung mindestens einmal heißt: Ein Ereignis kann mehrfach ankommen, weil ein Sender nach einem Timeout wiederholt oder weil FORGE nach einem Neustart ab dem zuletzt festgeschriebenen Offset liest. FORGE setzt darum jedes Ereignis idempotent um. Jedes Ereignis trägt eine Kennung und je Schlüssel eine fortlaufende Nummer oder die Logposition der Quelle. Die Ontologie nimmt es nur an, wenn die Nummer größer ist als die zuletzt angewandte, und verwirft es sonst.
Kafka kennt eigene Garantien: idempotente Sender und Transaktionen, mit denen sich Lesen, Verarbeiten und Schreiben zwischen Themen von Kafka genau einmal vollziehen lässt, wenn die Leser nur festgeschriebene Nachrichten lesen (read_committed). Diese Garantie endet an der Grenze von Kafka. Ein Schreiben in eine andere Datenbank ist nicht Teil der Kafka-Transaktion. FORGE sichert den letzten Schritt deshalb selbst: Die Nummer des Ereignisses steht in derselben Datenbanktransaktion wie die Änderung in der Ontologie.
Den Offset schreibt FORGE erst fest, nachdem die Änderung bestätigt ist. Fällt es dazwischen aus, liest es dieselben Ereignisse erneut, und die Nummern verwerfen sie.
Ereignis = ( kennung, schluessel, nummer,
ereigniszeit, aufnahmezeit, nutzlast )
anwenden(e):
nummer ≤ angewandt(schluessel) verwerfen Doppel oder Nachzügler
nummer = angewandt(schluessel) + 1 anwenden Änderung und Nummer in einer Transaktion
sonst zurückstellen Lücke: auf den Vorgänger wartenEin Ereignis, drei Ausgänge
Ein Ereignis wird geprüft, gegen die Nummer gehalten und mit ihr geschrieben. Ein Doppel endet im Verwerfen, ein nicht lesbares Ereignis in der Fehlerspur. Der Offset rückt erst nach dem Schreiben.
- Ablauf von Ereignis bis Aussage: Prüfen, Nummer, Schreiben, Offset, Fehlerspur, Verwerfen.
- Prüfen zu Nummer.
- Nummer zu Schreiben.
- Schreiben zu Offset.
- Prüfen nicht lesbar Fehlerspur.
- Nummer Doppel Verwerfen.
Verspätete Ereignisse
Auch in einem geordneten Strom kommt ein Ereignis manchmal erst an, nachdem spätere schon verarbeitet sind: Ein Gerät sendet nach einem Funkloch gesammelt nach, ein Vorsystem schreibt mit Verzug. Fenster über der Ereigniszeit schließen darum nicht mit der Uhr, sondern anhand eines Wasserzeichens, der Schätzung, bis zu welcher Ereigniszeit alles da ist. Das Konzept stammt aus der Forschung zur Stromverarbeitung und ist in Werkzeugen wie Apache Flink üblich.
Ein Ereignis, das nach dem Wasserzeichen kommt, wird nicht verworfen. Innerhalb einer erlaubten Verspätung korrigiert es das Fenster, das es betrifft. Danach läuft es als Korrektur in die Ontologie: Die alte Aussage schließt ihre Erfassungszeit, und eine neue mit derselben Gültigkeitszeit tritt an ihre Stelle. Eine frühere Auswertung bleibt so reproduzierbar, und die Verspätung ist als solche sichtbar.
Abgeleitete Werte, etwa Summen oder Zählungen über ein Fenster, werden nach einer Korrektur neu berechnet und mit neuer Erfassungszeit abgelegt. Wie lang die erlaubte Verspätung ist, steht je Strom an der Abbildung und nicht im Code.
Zustand und Wiederanlauf
Verarbeitung mit Gedächtnis, etwa das Zählen in einem Fenster oder das Zusammenführen zweier Ströme, hält Zustand. Er wird regelmäßig als Prüfpunkt gesichert, zusammen mit den Offsets, bis zu denen die Eingaben dafür gelesen sind. Das Verfahren, dafür die Ströme mit Markierungen zu durchlaufen, geht auf den Algorithmus von Chandy und Lamport für verteilte Schnappschüsse zurück.
Nach einem Ausfall stellt FORGE den letzten Prüfpunkt her und liest ab den gesicherten Offsets neu. Weil die Verarbeitung deterministisch und das Ende idempotent ist, ergibt dieselbe Strecke dasselbe Ergebnis. Dieselbe Eigenschaft erlaubt es, eine fehlerhafte Verarbeitung zu korrigieren und den Strom ab einem früheren Offset erneut laufen zu lassen.
Die Aufbewahrung des Logs ist begrenzt. Was weiter zurückreicht, als der Strom hält, liegt nur in der Rohzone, in die jedes Ereignis unverändert und anhängend geschrieben wird, bevor es weiterläuft. Der Strom ist der schnelle Weg, die Rohzone die Quelle für Wiederholungen.
Rückstau und nicht lesbare Ereignisse
Kommt ein Strom schneller an, als FORGE verarbeitet, wächst der Rückstand im Log, der Abstand zwischen dem letzten Eintrag und dem gelesenen Offset (Consumer Lag). FORGE misst ihn je Strom und Partition und meldet bei einer Schwelle. Puffer im Speicher bleiben begrenzt, damit ein Stau nicht als Speicherfehler endet: Das Log nimmt den Stau auf, und die Leser holen auf, bis ihre Zahl die der Partitionen erreicht.
Ein Ereignis, das nicht dem Schema entspricht oder dessen Nutzlast nicht gelesen werden kann, darf den Strom nicht anhalten. Es geht mit Grund, Fundstelle und den Originalbytes in eine Fehlerspur (Dead-Letter-Topic) und wird dort geprüft. Weil damit die Ordnung dieses Schlüssels reißt, markiert FORGE das Objekt als offen, bis das Ereignis geklärt und nachgeholt ist. Wo ein Objekt strikte Ordnung braucht, hält stattdessen die Partition an; das ist je Strom eine bewusste Einstellung.
Das Schema der Nutzlast steht in einem Schema-Register, mit Avro, JSON Schema oder Protobuf. Eine Änderung muss mit der Kompatibilitätsregel des Stroms verträglich sein, bevor ein Sender sie verwendet.
Eckdaten
- Log
- Apache Kafka; Partition je Schlüssel, Offset je Partition
- Ordnung
- je Schlüssel; der Schlüssel ist die Identität des Objekts
- Zustellung
- mindestens einmal; Wirkung genau einmal durch die Nummer je Schlüssel
- Kafka-Transaktionen
- genau einmal innerhalb von Kafka, Leser mit
read_committed - Zeit
- Ereigniszeit wird Gültigkeitszeit, Aufnahmezeit wird Erfassungszeit
- Verspätung
- Wasserzeichen, erlaubte Verspätung je Strom, danach Korrektur mit neuer Erfassungszeit
- Wiederanlauf
- Prüfpunkt mit Offsets; für längere Strecken die Rohzone
- Fehler
- Fehlerspur (Dead-Letter-Topic); Rückstand als Größe mit Schwelle
- Schema
- Schema-Register mit Avro, JSON Schema, Protobuf; Kompatibilitätsregel je Strom
Weiter
- FORGE · TechnikAnbindungWie FORGE Datenbanken, SAP, Dateien und Ereignisströme anbindet, Änderungen aus dem Log der Quelle liest und jedem Feld seine Herkunft mitgibt.
- FORGE · TechnikOntologieWie FORGE Zeilen auf Objekttypen abbildet, dasselbe Objekt über Quellen hinweg erkennt und zu jedem Wert Gültigkeitszeit und Erfassungszeit führt.
- FORGE · TechnikRückschreibenWie eine Handlung geprüft, über die Schnittstelle der Quelle geschrieben, gegen doppelte Ausführung gesichert und bei Teilfehlern ausgeglichen wird.
- FORGE · TechnikPipelinesWie FORGE Transformationen als Quelltext mit Version und Tests führt, Abhängigkeiten als Graph baut und jede Ausgabe bis zur Rohzeile zurückverfolgt.
- FORGE · TechnikZweigeWie FORGE Änderungen an Ontologie, Abbildungen und Transformationen auf einem Zweig rechnet, vergleicht und erst nach Freigabe zusammenführt.
- ProduktFORGEBetrieb und Daten einer Organisation an einem Ort
Welcher Ihrer Ströme darf nie zweimal wirken? An ihm legen wir mit Ihnen Schlüssel und Nummer fest.