Apache Kafka

Apache Kafka ist eine schlanke Message Queue, deren Kernfeatures, im Vergleich zu etwa Apache ActiveMQ, besonders stark auf Skalierbarkeit, Performance und Fehlertoleranz ausgerichtet sind.

In diesem Artikel soll es um eine Einführung in Apache Kafka gehen. Dabei wird insbesondere auf die Fragen, was Apache Kafka eigentlich ist, wie es funktioniert und in welchen Use Cases der Einsatz von Apache Kafka Sinn ergeben könnte, eingegangen.

Was ist Apache Kafka?

Apache Kafka ist ein verteiltes Messaging-System. Es wurde von LinkedIn entwickelt und ist seit 2011 Open Source. Implementiert wurde es hauptsächlich in Scala und etwas Java. Es ermöglicht eine entkoppelte, asynchrone Kommunikation zwischen mehreren Komponenten einer Anwendung. Dabei basiert Kafka auf einem verteilten Public-Subscribe System. Apache Kafka ist allerdings keine Implementierung des Java Messaging Frameworks (JMS). Der Fokus bei Apache Kafka liegt stärker auf der Performance und Skalierbarkeit. Somit werden weitaus weniger Features mitgebracht, als beispielsweise in der JMS-Implementierung Apache ActiveMQ. Um die Transaktionssicherheit zu gewährleisten, beinhaltet Kafka ein verteiltes Commit Log vergleichbar mit einem verteilten Datenbanksystem. Zusätzlich werden alle Nachrichten und zentrale Stellen im Cluster repliziert. Dadurch kann Apache Kafka sehr hohe Fehlertoleranz-Garantien bei guter Skalierbarkeit und Performance erreichen.

Welchem Zweck soll Apache Kafka dienen?

LinkedIn beschreibt als eigene Motivation für Apache Kafka, dass es eine einheitliche Plattform zur Verarbeitung aller Echtzeit-Datenströme innerhalb eines großen Unternehmens darstelle. Ziele sind neben einem hohen Durchsatz und einer Verarbeitung der Streams in Echtzeit die Unterstützung großer Datenbacklogs (z. B. bei der Übernahme von Offline-Systeme). Die hohe Fehlertoleranz durch das verteilte Commit-Log soll Ausfälle einzelner Clusterknoten abfangen und bei der Disaster Recovery den letzten gültigen Zustand wiederherstellen, ohne dass Nachrichten verloren gehen.

Wann ist der Einsatz von Apache Kafka sinnvoll?

Sinnvoll ist der Einsatz insbesondere dann, wenn der Hauptfokus auf besonders guter Performance mit hohem Durchsatz, aber ebenfalls hoher Ausfallsicherheit liegt. Insbesondere dann, wenn die zusätzlichen Features von JMS nicht benötigt werden, kann über den Einsatz von Kafka als Message Queue nachgedacht werden. Der initiale Use Case von Apache Kafka bei LinkedIn ist im Bereich des sogenannten Website Activity Tracking. Dabei geht es um die Verarbeitung von Meta-Daten über das Benutzerverhalten, etwa Page Views oder präferierte Suchergebnisse. Auch das Monitoring von technischen Betriebsdaten über beispielsweise Auslastung der Clusterknoten gehört zu einem Einsatzgebiet von Kafka. Dies lässt sich durch die Aggregation und Analyse von Offline-Logs erweitern. Kafka kann außerdem den Input für komplexe Stream-Verarbeitung, beispielsweise mit Apache Spark, liefern.

Wie funktioniert Apache Kafka?

Um die hohe Performance und Geschwindigkeit zu erreichen, optimiert Kafka bereits bei den Lese- und Schreibvorgängen. Alle zu persistierenden Daten werden zunächst in den Arbeitsspeicher des Betriebssystems geschrieben. Anschließend werden sie persistiert. Beim Lesen wird ein besonders effizienter Transfer vom RAM zum Netzwerk-Socket gewährleistet. Unter Linux geschieht dies beispielsweise über einen Aufruf der sendfile(…)-Prozedur.

Apache Kafka organisiert die einzelnen Data Streams über Topics. Ein Topic kann über mehrere Broker repliziert werden. Für alle Nachrichten wird eine Aufzeichnung in Form eines Records als Dreitupel mit einem Schlüssel, Wert und Zeitstempel gespeichert. Diese Records werden in das oben bereits angesprochene verteilte Commit-Log persistiert, indem sie in eine sogenannte Partition abgelegt werden. Eine Partition ist eine Menge von Records, die über eine Sequenznummer nummeriert sind. Diese Nummerierung wird auch Offset genannt. Innerhalb eines Records herrscht totale Ordnung, innerhalb eines Topics, welches aus mehreren Records besteht, ist diese nicht gewährleistet.

Die Consumer können einfach auf diese Records zugreifen, indem sie auf jeden Record über den entsprechenden Offset innerhalb der zugehörigen Partition zugreifen können. Ein Consumer kann also die Records in einer beliebigen Reihenfolge abrufen. Auch kann er ältere Records erneut anfordern, indem er die Records am passenden Offset anfordert. Somit können beliebig viele Consumer unabhängig voneinander und seiteneffektfrei auf einem Topic operieren.

Des Weiteren können die Partitionen beliebig auf die Clusterknoten verteilt und repliziert werden. Durch die Partitionierung ist es möglich, auch Nachrichtenreihen auf Topics zu verwalten, die mehr Platz beanspruchen oder mehr Zugriffe verarbeiten müssen, als mit einer einzelnen physischen Maschine möglich wäre. Ein Topic kann also dank der Partitionierung über mehrere physische Maschinen verteilt werden. Jede replizierte Partition besitzt damit einen Master und beliebig viele Slaves. Der Master verarbeitet dabei alle Lese- und Schreiboperationen, während die Slaves nur passive Replikate darstellen. Beim Absturz des Masters kann aufgrund des verteilten Commit-Logs die Transaktionssicherheit gewahrt werden, und einer der Slaves wird automatisch zum neuen Master. Zusätzlich wird gewährleistet, dass die Master der Partitionen so verteilt sind, dass jeder physische Clusterknoten einige Master und einige Slaves für unterschiedliche Topics hat, um die Last besser über die Clusterknoten zu verteilen.

Der Producer kann jede Nachricht auf ein oder mehr beliebige Topics pushen. Er ist dabei dafür verantwortlich, auf welche Partition seine Nachricht gepusht wird. Dies kann beispielsweise per Round Robin oder Hashfunktion entschieden werden.

Die Consumer können Teil einer Consumer Group sein. Jede Nachricht auf einem Topic wird vom Message Broker an jeweils einen Consumer in jeder Consumer Group, die das Topic abonniert hat, ausgeliefert. Somit können auch die Consumer mit einfachen Mitteln repliziert werden.

Apache Kafka als Publish-Subscribe-System

In Abbildung 1 ist das verteilte Publish-Subscribe-System von Apache Kafka visualisiert.

Abbildung 1: Publish-Subscribe

Abbildung 1: Publish-Subscribe

Die Skizze ist ähnlich der aus dem Artikel über Apache Active MQ. Nur gibt es hier statt nur einem Broker ein ganzes Cluster an Brokern. Der Publisher kann nun seine Nachricht an ein Topic des Message Brokers schicken, und der Subscriber kann auf ein Topic des Message Brokers subscriben. Dass der Message Broker intern aus einem Cluster besteht, welches die Last auf mehrere redundante Message Broker verteilt, ist von außen nicht direkt erkennbar.

Im Übrigen kann ein Topic in Kafka 0 bis n Consumer haben. Damit ist nicht sichergestellt, dass überhaupt jemand auf dem Topic registriert ist, wenn ein Publisher eine Nachricht auf das Topic publisht. Daher werden alle Nachrichten gespeichert. Wie viele Nachrichten und für wie lange diese gespeichert werden, kann für jedes Topic separat konfiguriert werden. Konkret wird das Apache Kafka Cluster von einer Apache ZooKeeper Instanz orchestriert (siehe Abbildung 2).

Abbildung 2: Apache Kafka mit ZooKeeper

Abbildung 2: Apache Kafka mit ZooKeeper

Zunächst schickt der Publisher eine Nachricht an den ZooKeeper, um eine BrokerID für seine Nachricht zugeteilt zu bekommen. Nachdem die ZooKeeper-Instanz diese BrokerID zurückgeschickt hat, pusht der Publisher seine Nachricht an das Kafka-Cluster an den Broker mit der entsprechenden BrokerID. Da die Nachrichten auf den Brokern sequenziell abgelegt werden, lässt sich das Nachrichtenoffset für die neue Nachricht auf dem ausgewählten Broker leicht bestimmen. Diesen Offset leitet ZooKeeper dann an den Subscriber weiter. Der Subscriber kann sich anschließend die neue Nachricht mit Hilfe des empfangenen Offsets vom Kafka Cluster abholen.

Fazit

Apache Kafka ist eine schlanke Message Queue, welche besonders stark auf Skalierbarkeit, Performance und Fehlertoleranz ausgerichtet ist. Dazu wird auf einige Komfortfunktionen verzichtet, etwa auf die Unterstützung für eine Exactly-Once Auslieferung der Nachrichten. Stattdessen läuft die Auslieferung pullbasiert ab und jeder Consumer kann über den Offset genau die Nachrichten abrufen, die gerade benötigt werden. Auch die Geschwindigkeit des Nachrichtenempfangs bestimmt jeder Consumer selbst. Ein Consumer kann eine Nachricht auch mehrmals abrufen, wenn es zu einem Fehler in der Verarbeitung gekommen ist.

Short URL for this post: https://wp.me/p4nxik-2TN
This entry was posted in Java Runtimes - VM, Appserver & Cloud and tagged , , , , . Bookmark the permalink.

2 Responses to Apache Kafka

  1. Pingback: Apache Kafka auf der Konsole | techscouting through the java news

  2. Pingback: Apache Kafka in Java | techscouting through the java news

Leave a Reply