Beyond Bytes: Die vier Nachrichtentypen in Kafka verstehen

Kafkas Flexibilität ist ein zweischneidiges Schwert. Dieser Leitfaden stellt die vier primären Nachrichtentypen vor: States, Deltas, Events und Commands. Er zeigt Ihnen, wie Ihr Eure Datenströme zielgerichtet gestalten könnt, was zu robusten und skalierbaren Architekturen führt.

Apache Kafka bietet immense Flexibilität. Es kann jede Art von Daten verarbeiten, JSON-Objekte, Avro oder sogar benutzerdefinierte Binärformate. Aber mit dieser Flexibilität kommt eine entscheidende architektonische Herausforderung: Ihr müsst euch selbst überlegen, welche Art von Daten durch Eure Topics fließen.

Ohne eine klare Strategie können Eure Datenströme schnell zu einem chaotischen Durcheinander unstrukturierter Bytes werden, was zu inkonsistenten Daten, fragilen Systemen und endlosem Debugging führt. Dieser Leitfaden bietet einen Rahmen zur Definition Eurer Kafka-Nachrichten basierend auf ihrem Zweck. Wir werden die vier primären Nachrichtentypen erkunden: States, Deltas, Events und Commands und zeigen, wie eine bewusste Wahl zu robusteren, skalierbaren und verständlicheren Datenarchitekturen führt.

Was ist eine Kafka-Nachricht wirklich?

Im Kern ist eine Kafka-Nachricht oder ein Record nichts anderes als ein einfaches Byte-Array. Kafka ist auf Performance getrimmt und kümmert sich nicht um den Inhalt Eurer Nachricht. Es liegt an Euch, sie zu interpretieren. Die Nachricht selbst besteht aus einem optionalen Key, einem Value (der Payload), einem optionalen Zeitstempel und einer Reihe von benutzerdefinierten Headern für technische Metadaten.

Während Kafka jedes Byte-Array verarbeiten kann, ist es für eine hohe Anzahl kleiner Nachrichten optimiert, die typischerweise unter 1MB bleiben. Der Versuch, große Dateien durch Kafka zu pushen, kann zu schlechter Performance führen und sollte vermieden werden.

Lass uns nun die vier Möglichkeiten erkunden, wie Ihr dieses Byte-Array nutzen könnt, um Eure Datenströme zu gestalten.

Die vier Säulen des Message-Designs

Die folgenden Typen schließen sich nicht gegenseitig aus. Ein einzelnes System verwendet oft eine Mischung aus ihnen, um seine Ziele zu erreichen. Lass uns ein praktisches Szenario verwenden, um jeden Typ zu veranschaulichen: Ein User aktualisiert seine Wohnadresse in einem Stammdaten-Service.

1. States: Die "Was ist" Nachricht

Eine State-Nachricht stellt die vollständige, aktuelle Momentaufnahme eines Objekts dar. Es ist ein vollständiges Bild des Objekts zu einem bestimmten Zeitpunkt, das alle seine Attribute enthält.

  • Szenario: Wenn sich die Adresse eines Benutzers ändert, könnte ein user.state Topic ein vollständiges Benutzerobjekt mit der neuen Adresse erhalten.

  • Zweck: Dieser Typ ist unschätzbar, wenn Ihr einfach den neuesten Zustand eines Objekts haben möchtet. Vielleicht möchtet Ihr den neuesten Zustand eines Benutzers an eine Datenbank eines anderen Services pushen. Dann nutzt diese Nachrichtenart.

{
  "userId": "user-12345",
  "name": "Jane Doe",
  "email": "jane.doe@example.com",
  "address": {
    "street": "123 Main Street",
    "city": "Anytown",
    "zip": "12345"
  }
}
  • Vorteile: Einfach zu verarbeiten, da jede Nachricht in sich geschlossen ist. Neue Consumer können schnell das vollständige Bild erhalten.

  • Nachteile: Hohes Datenvolumen, besonders bei großen Objekten mit häufigen, kleinen Änderungen. Es ist schwierig zu verstehen, was genau geändert wurde und warum, da die Nachricht nur den Endzustand enthält.

2. Deltas: Die "Was hat sich geändert" Nachricht

Eine Delta-Nachricht enthält nur die Attribute einer Entität, die sich geändert haben. Es ist ein partielles Update, das eine Differenz zwischen dem alten und dem neuen Zustand darstellt.

  • Szenario: Anstatt das gesamte Benutzerobjekt zu senden, sendet der Stammdaten-Service eine user.address.changes Nachricht, die nur die Benutzer-ID und die aktualisierte Adresse enthält.

  • Zweck: Delta-Nachrichten sind sehr effizient für häufige Updates, bei denen sich nur wenige Felder ändern. Ein konsumierender Service weiß sofort, was sich geändert hat und kann entsprechend handeln. Wenn er den vorherigen Zustand des Benutzers hat, kann er ihn leicht aktualisieren.

{
  "userId": "user-12345",
  "address": {
    "street": "123 Main Street",
    "city": "Anytown",
    "zip": "12345"
  }
}
  • Vorteile: Höhere Effizienz durch minimales Datenvolumen. Eine klare und prägnante Darstellung dessen, was sich geändert hat.

  • Nachteile: Erfordert, dass der Consumer einen lokalen State pflegt, um ein vollständiges Bild zu erstellen. Wenn eine Nachricht verpasst wird, wird der lokale Zustand falsch sein. Es bietet auch keinen Einblick in das Warum der Änderung. Hat der Benutzer einen Tippfehler korrigiert oder ist er tatsächlich umgezogen?

Deltas können zu Dateninkonsistenzen führen, wenn eine konsumierende Anwendung eine Nachricht verpasst.

3. Events: Die "Was ist passiert" Nachricht

Eine Event-Nachricht beschreibt eine spezifische Aktion oder ein Ereignis, das für das Business relevant ist. Sie enthält oft kontextuelle Informationen über die Daten hinaus, die sich geändert haben.

  • Szenario: Wenn ein Benutzer tatsächlich umzieht, emittiert der Stammdaten-Service ein user.moved Event an ein Audit-Topic. Wenn das Backoffice einfach einen Tippfehler korrigiert, könnte es ein user.corrected Event emittieren. Die Event-Payload enthält die ID der geänderten Entität, den Event-Typ und die Payload. Die Payload ist normalerweise entweder eine State-Nachricht oder eine Delta-Nachricht.

  • Zweck: Events sind das Fundament ereignisgesteuerter Architekturen. Sie bieten ein unveränderliches Audit-Log von Geschäftsaktionen. Andere Services können auf dieses Event reagieren, ohne eng an den Producer gekoppelt zu sein. Zum Beispiel kann ein Audit-System das Event protokollieren, oder der Umzugs-Postkarten-Service kann eine Postkarte an den Benutzer senden, wenn der tatsächliche Umzug stattfindet.

{
  "event": "user.moved",
  "userId": "user-12345",
  "payload": {
    "address": {
      "street": "123 Main Street",
      "city": "Anytown",
      "zip": "12345"
    }
  }
}
  • Vorteile: Bietet eine semantische Bedeutung. Du weißt nicht nur, was sich geändert hat, sondern auch warum etwas passiert ist, was für komplexe Geschäftslogik entscheidend ist.

  • Nachteile: Kann zu "Event-Überlastung" führen, wenn ein separates Event für jede kleine Aktion erstellt wird. Eine konsumierende Anwendung benötigt ihre eigene Logik, um das Event zu verarbeiten und ihren Zustand zu aktualisieren, was komplexer ist als nur eine State-Nachricht anzuwenden.

4. Commands: Die "Was zu tun ist" Nachricht

Eine Command-Nachricht ist eine explizite Anweisung für einen anderen Service, eine spezifische Aktion auszuführen. Im Gegensatz zu einem Event ist sie zukunftsorientiert und an einen einzelnen Empfänger gerichtet.

  • Szenario: Nach dem Konsumieren des user.moved Events verarbeitet ein "Umzugs-Postkarten-Service" die Änderung und produziert einen Command an ein postcard.sender Topic. Der Befehl weist den Postkarten-Service an, eine Postkarte mit der neuen Adresse und einer personalisierten Nachricht zu senden.

  • Zweck: Commands werden für direkte, explizite Kommunikation zwischen Services verwendet. Der Ziel-Service kann sich auf seine Aufgabe konzentrieren, ohne die zugrundeliegende Geschäftslogik ("das Warum") hinter der Aktion verstehen zu müssen. Er führt einfach den Befehl aus.

{
  "command": "send.postcard",
  "name": "John Doe",
  "address": {
    "street": "123 Main Street",
    "city": "Anytown",
    "zip": "12345"
  },
  "message": "Willkommen in Deinem neuen Zuhause!",
  "image-url": "https://example.com/postcard.jpg"
}
  • Vorteile: Explizite und direkte Kommunikation. Der Zweck ist klar und die Logik des empfangenden Services ist unkompliziert. Der empfangende Service muss die zugrundeliegende Geschäftslogik ("das Warum") hinter der Aktion nicht verstehen.

  • Nachteile: Erzeugt eine engere Kopplung zwischen Producer und Consumer. Ein neuer Consumer kann einen Befehl nicht einfach für einen anderen Zweck wiederverwenden, was ihn weniger flexibel als ein Event macht.

Fazit

Die Wahl des Nachrichtentyps ist eine grundlegende architektonische Entscheidung, nicht nur ein technisches Detail. Wie wir in unserem Beispiel der Adressänderung gesehen haben, kann eine einzelne Aktion auf verschiedene Weise dargestellt werden, wobei jede einem anderen Zweck dient.

  • States sind perfekt, um das vollständige aktuelle Bild einer Entität zu erfassen.

  • Deltas sind ideal für effiziente, partielle Updates, um Daten frisch zu halten.

  • Events sind das Fundament entkoppelter, ereignisgesteuerter Systeme und sagen, was passiert ist.

  • Commands sind für explizite, gerichtete Anweisungen und sagen einem Service, was zu tun ist.

Durch die bewusste Wahl des richtigen Nachrichtentyps für jeden Geschäftsprozess könnt Ihr Systeme nicht nur performant und skalierbar, sondern auch klar, wartbar und robust bauen.

Über Anatoly Zelenin
Hallo, ich bin Anatoly! Ich liebe es, bei Menschen das Funkeln in den Augen zu wecken. Als Apache Kafka Experte und Buchautor bringe ich seit über einem Jahrzehnt IT zum Leben - mit Leidenschaft statt Langeweile, mit Erlebnissen statt endlosen Folien.

Weiterlesen

article-image
Apache Kafka im Überblick

Unternehmen nutzen Apache Kafka, um Entscheidungen nahezu in Echtzeit zu treffen. Diese Datendrehscheibe und Event-Streaming-Plattform ermöglicht Antworten in dem Moment, in dem die Fragen aufkommen, und hilft Organisationen dabei, vom Warten zum Handeln zu kommen.

Mehr lesen
article-image
Apache Kafka – Von den Grundlagen bis zum Produktiveinsatz

Apache Kafka – Von den Grundlagen bis zum Produktiveinsatz begleitet dich durch die Konzepte und Fertigkeiten, die du benötigst, um Kafka für Datenpipelines, Event-getriebene Anwendungen und andere Systeme einzusetzen und zu administrieren, die Datenströme aus mehreren Quellen verarbeiten.

Mehr lesen