Apache Kafka hat sich seit seiner Open-Source-Veröffentlichung als der Quasi-Standard für verteilte Messaging-Systeme etabliert. Ursprünglich für lokale Rechenzentren konzipiert, stößt Kafka bei der Skalierung in modernen Cloud-Umgebungen auf zahlreiche Herausforderungen. Insbesondere wenn es darum geht, Kafka mit einer kosteneffizienteren Speicherlösung wie Amazon S3 zu betreiben, ergeben sich erhebliche technische Schwierigkeiten, die weit über den reinen Datentransfer hinausgehen. Die Integration von Kafka und S3 verpflichtet Entwickler, mit fundamentalen Unterschieden zwischen traditionellen dateibasierten Speichersystemen und objektbasiertem Speicher umzugehen und gleichzeitig die Kompatibilität und Performance zu gewährleisten. Diese tiefergehende Analyse widmet sich den Kernproblemen, die sich bei diesem Vorhaben ergeben, und zeigt auf, wie innovative Ansätze diese Herausforderung meistern.
Kafka wurde von Grund auf für lokale Speicher optimiert. In einem typischen Kafka-Cluster werden Daten auf physischen Festplatten von Broker-Maschinen persistiert. Die Kopplung von Speicher und Rechenleistung in diesem Modell ist ein zentrales Designmerkmal, führt aber auch zu Einschränkungen. Skalierung des Speichers erfordert das Hinzufügen weiterer Knoten, was Ressourcen- und Kostenineffizienzen mit sich bringt. Die Replikation von Daten zur Gewährleistung von Haltbarkeit und Ausfallsicherheit erfolgt über die Kafka-eigene Architektur und benötigt Netzwerkkommunikation zwischen den Knoten.
In Cloud-Umgebungen, insbesondere bei Angeboten wie AWS, entstehen dabei beträchtliche Kosten durch Datentransfers zwischen verschiedenen Availability Zones. Object Storage wie Amazon S3 bringt hier eine attraktive Alternative mit sich, da er kosteneffizient, skalierbar und hochverfügbar ist. Allerdings sind Objekt-Storage-Systeme auf andere Weise aufgebaut. Die Speicherung ist immutable, das heißt, Objekte können nicht einfach angefügt oder verändert werden, wie dies bei Dateien auf einem Dateisystem möglich ist. Außerdem sind die Latenzzeiten für Lese- und Schreiboperationen in S3 deutlich höher im Vergleich zu lokalen NVMe-SSDs oder selbst Cloud-gebundenen Blockspeichern.
Diese Unterschiede rufen zentrale Herausforderungen hervor, die bei der Integration von Kafka und S3 sorgfältig adressiert werden müssen. Eine der offensichtlichsten Hürden ist die Latenz. Während traditionelle Kafka-Broker Daten mit Mikrosekundenlatenz schreiben und lesen, sind typische GetObject-Anfragen an S3 um Faktoren langsamer. Dies wirkt sich insbesondere auf die Zeit aus, bis eine Nachricht bestätigt und an den Produzenten zurückgemeldet wird. Produkte wie WarpStream oder Bufstream akzeptieren diese Latenz als Kompromiss zugunsten der Kosteneinsparung, indem sie Nachrichten erst dann als bestätigt gelten lassen, wenn sie in S3 gespeichert sind.
Andere Lösungen wie AutoMQ verfolgen einen hybriden Ansatz, bei dem Nachrichten zunächst in einem Write Ahead Log (WAL) auf einem schnellen Blockspeicher wie AWS EBS persistiert werden. Die anschließende Speicherung in S3 erfolgt asynchron. Dies ermöglicht niedrige Latenzen für Schreiboperationen mit einem P99-Wert von unter 10 Millisekunden, ohne die Datenhaltbarkeit zu kompromittieren. Die Auseinandersetzung mit Input/Output-Operationen pro Sekunde (IOPS) ist ein weiterer kritischer Punkt. Amazon S3 verrechnet PUT-Anfragen, was bei hohem Durchsatz erheblich ins Geld gehen kann.
Um die Kosten zu minimieren, setzen alle Anbieter auf Daten-Pufferung und Batch-Verarbeitung. Die clevere Bündelung von Daten aus unterschiedlichen Partitionen oder sogar aus verschiedenen Themen in sogenannte Stream Set Objects (SSO) oder Stream Objects (SO) hilft, die Anzahl der PUT-Anfragen zu senken. Die Herausforderung hierbei liegt in der Ordnung und Optimierung der gespeicherten Objekte, da eine zu starke Streuung der Daten aus einer einzelnen Partition die Effizienz von Leseoperationen beeinträchtigen kann. AutoMQ begegnet diesem Problem mit einem Hintergrundprozess zur Kompaktierung, der Objekte zusammenführt und so eine physische Nähe der Daten innerhalb einer Partition herstellt. Dies sorgt für spürbar bessere und sequenzielle Leseperformance.
Das Caching stellt eine entscheidende Technik dar, um die mit den Latenzen und IOPS verbundenen Nachteile des objektbasierten Speichers auszugleichen. Eine hohe Cache-Trefferquote reduziert die Anzahl der direkten Zugriffe auf S3 und verbessert die Antwortzeiten bei Leseanforderungen erheblich. Während manche Anbieter die Last über verteilte Agenten mittels konsistenter Hashing-Ringe balancieren, verfolgt AutoMQ den Ansatz, die sogenannte Datenlokalität zu bewahren – ähnlich wie in Kafka. Jede Broker-Instanz cached Daten von jenen Partitionen, für die sie verantwortlich ist. Durch differenziertes Management von Log-Caches für aktuelle Schreib- und Lesezugriffe und Block-Caches für historische Daten lässt sich die Performance erheblich steigern und die Systemlast auf Objekt-Storage reduzieren.
Die Notwendigkeit eines ausgeklügelten Metadatenmanagements ergibt sich aus den Eigenarten von Objekt-Storage-Systemen. Kafka kann in lokalen Dateisystemen Verzeichnisse und Dateien durchsuchen, die Segmente einer Partition darstellen. In S3 sind solche Verzeichnisse jedoch nur durch LIST-Anfragen ersetzbar, die vergleichsweise langsam und teuer sind. Systeme, die Kafka auf S3 emulieren, müssen daher zusätzliche Metadatenstrukturen weiter pflegen. Dazu zählen beispielsweise Informationen darüber, welche Objekte zu welchen Topics und Partitionen gehören und wie Nachrichten in der richtigen Reihenfolge wiederhergestellt werden können.
Auch die Anzahl der Metadatenobjekte sollte begrenzt werden, um die Komplexität zu handhaben, weshalb Kompaktierungsprozesse wie bei AutoMQ von essenzieller Bedeutung sind. Neben der Datenspeicherung erfordert das Funktionsprinzip von Kafka auch ein ausgefeiltes Management der Cluster-Metadaten. Hierzu zählen Broker-Registrierung, Topic-Konfigurationen und Konsistenz der Replikate. Während ältere Kafka-Installationen hierfür Zookeeper verwenden, kommen neuere Varianten auf Basis von Kraft (Kafka Raft Metadata Mode) ohne Zookeeper aus. AutoMQ orientiert sich am Kraft-Modell, behält eine Controller-Quorum-Struktur bei und verwaltet die Cluster-Metadaten zentral und repliziert sie an alle Broker.
Diese Herangehensweise ist für die Konsistenz in verteilten Cloud-Architekturen entscheidend. Die Wahrung der Kafka-Kompatibilität stellt eine besonders große Herausforderung dar. Kafka setzt auf lokale, an die Partition gebundene Logs und nutzt Indices, um schnelle Offsetsuchen, Transaktions- und Zeitstempelabfragen zu realisieren. Das objektbasierte Speichermodell lässt jedoch keine appendbaren Parallelen zum Dateisystem zu. Einige Systeme wählen daher die vollständige Neuentwicklung des Protokolls, was Kompatibilitätsprobleme mit sich bringen kann.
AutoMQ hingegen bewahrt das Kafka-Protokoll fast vollständig und ändert lediglich die Speicher-Engine. Dazu führt es eine neue Abstraktion, die Streams über Segmente legt, ein, die das Schreiben, Cachen und asynchrone Offloading auf Objekt-Storage ermöglichen. Die Speicherarchitektur verbindet so die Flexibilität von Object Storage mit der Architektur von Kafka, die weiterhin Partitionen und Segmente verwendet. Die Kombination von Shared-Nothing- und Shared-Disk-Architekturen bringt weitere Überlegungen mit sich. Kafka basiert auf einem Shared-Nothing-Konzept, bei dem Partitionen an dedizierte Broker gebunden sind, was eine effiziente Datenlokalität und Lastverteilung ermöglicht.
Auf der anderen Seite erleichtert ein Shared-Disk-System wie S3 die Datenverteilung über mehrere Knoten, da alle auf dieselben Objekte zugreifen können. AutoMQ versucht, beide Welten zu vereinen – die Partitionen bleiben logisch Broker-gebunden, während das physische Daten-Hosting vollständig in S3 ausgelagert wird. Das wirft Fragen bezüglich Datenlokalität und Datenverkehr auf, besonders in Bezug auf kostenintensive cross-AZ-Transfers. Cloud-Anbieter berechnen Gebühren für Datenübertragungen zwischen Availability Zones, was durch die Replikationsarchitektur von Kafka verstärkt wird. AutoMQ mindert dieses Problem, indem es bei Schreiboperationen zuerst lokal in einer AZ einen Broker ansteuert und den eigentlichen Leader asynchron informiert.
Dadurch wird die Anzahl direkter cross-AZ-Schreiboperationen minimiert, ohne die Datenkonsistenz zu gefährden. Der Netzwerk-Durchsatz dient dabei als limitierender Faktor. Aufgrund von Bandbreitenbegrenzungen sorgt AutoMQ mit einem prioritätsbasierten, token-bucket-gestützten Rate-Limiter für eine optimierte Verteilung der unterschiedlichen Datenverkehrsarten. Schreib- und Lesevorgänge der Producer und Consumer werden so effizient gesteuert und ein Überlasten der Infrastruktur vermieden. Diese vielschichtige Architektur zeigt beispielhaft, wie komplex die Aufgabe ist, Kafka vollständig auf einem Objekt-Storage wie S3 zu betreiben, aber auch, wie durchdachte Lösungen diese Herausforderungen praktisch lösen können.