Mastering der Kafka-Topic-Konfiguration: Ein umfassender Leitfaden

Ein praktischer Leitfaden zu Kafka-Topic-Partitionen, Replikation, Aufbewahrung, Kompaktierung und sicheren Konfigurationsänderungen.

Mastering der Kafka-Topic-Konfiguration: Ein umfassender Leitfaden

Die Kafka-Topic-Konfiguration bestimmt, wie Ihre Daten gespeichert, kopiert, ablaufen, kompaktiert und konsumiert werden. Sie können Kafka eine Weile mit den Standardeinstellungen betreiben, insbesondere in einem Entwicklungschuster, aber Produktionstopics benötigen mehr Sorgfalt. Eine schlechte Partitionsanzahl kann eine ausgelastete Arbeitslast einschränken. Schwache Replikation kann einen Broker-Ausfall in Datenverlust verwandeln. Lockere Aufbewahrung kann Festplatten füllen. Kompaktierung kann Sie überraschen, wenn Schlüssel fehlen oder inkonsistent sind.

Der sinnvolle Ansatz zur Kafka-Topic-Konfiguration besteht nicht darin, jede Einstellung auswendig zu lernen. Beginnen Sie mit den Fragen, die ein echtes System stellt: Wie viel Parallelität benötige ich, wie lange müssen Daten verfügbar bleiben, wie viele Daten kann ich mir zu speichern leisten, was passiert bei einem Broker-Ausfall und benötigen Verbraucher eine vollständige Ereignishistorie oder nur den neuesten Wert pro Schlüssel?

Ein Topic ist in Partitionen aufgeteilt. Jede Partition ist ein geordnetes Protokoll. Kafka bewahrt die Reihenfolge innerhalb einer Partition, nicht über das gesamte Topic hinweg. Wenn alle Ereignisse für einen Kunden in der richtigen Reihenfolge verarbeitet werden müssen, verwenden Sie einen stabilen Schlüssel wie customer_id, damit diese Ereignisse in derselben Partition landen. Wenn Sie zufällig schlüsseln, erhalten Sie möglicherweise eine bessere Verteilung, verlieren aber die Reihenfolge pro Entität.

Die Partitionsanzahl ist eine der ersten Entscheidungen, die man bereut. Mehr Partitionen ermöglichen mehr Verbraucherparallelität, da innerhalb einer Verbrauchergruppe eine Partition zu einem bestimmten Zeitpunkt nur von einem Gruppenmitglied konsumiert wird. Wenn ein Topic sechs Partitionen hat, kann eine Verbrauchergruppe bis zu sechs Verbraucher für dieses Topic aktiv nutzen. Das Hinzufügen eines siebten Verbrauchers erhöht den Konsum für dieses Topic nicht, es sei denn, es gibt andere zugewiesene Partitionen.

Mehr Partitionen kosten auch etwas. Sie erhöhen Metadaten, offene Dateien, Replikationsarbeit, Leader-Wahlarbeit und Wiederherstellungszeit nach Broker-Ausfällen. Sehr hohe Partitionsanzahlen können Cluster-Operationen verlangsamen, selbst wenn jede Partition nur bescheidenen Datenverkehr hat. Es gibt keine universelle beste Anzahl. Ein kleines internes Topic kann mit drei Partitionen auskommen. Ein belebter Ereignisstrom benötigt möglicherweise Dutzende. Eine sehr große Kafka-Installation kann weit mehr verwenden, aber das sollte aus gemessenem Durchsatz und operativer Kapazität resultieren, nicht aus Gewohnheit.

Erstellen Sie ein Topic mit expliziten Einstellungen:

kafka-topics.sh --create   --bootstrap-server broker1:9092   --topic user-events.v1   --partitions 12   --replication-factor 3   --config min.insync.replicas=2

Der Topic-Name sollte auch eine Absicht tragen. Namen wie events oder data werden nutzlos, sobald der Cluster wächst. user-events.v1, billing-invoices.v1 oder inventory-adjustments.v1 sagt zukünftigen Betreibern, was der Stream ist, und gibt Ihnen Raum für eine spätere Schemaänderung.

Der Replikationsfaktor steuert, wie viele Kopien Kafka für jede Partition aufbewahrt. In der Produktion ist 3 ein üblicher Standard, da er einen Broker-Ausfall erlaubt, während noch eine andere Replik verfügbar ist. Das bedeutet nicht, dass Sie die Producer-Einstellungen ignorieren können. Wenn Producer acks=1 verwenden, kann Kafka Datensätze bestätigen, bevor die Follower sie kopiert haben. Für wichtige Topics kombinieren Sie den Replikationsfaktor drei mit dem Topic-Level min.insync.replicas=2 und Producer acks=all.

min.insync.replicas wird oft missverstanden. Es erstellt keine Replikate. Es gibt an, wie viele synchronisierte Replikate für einen acks=all-Schreibvorgang verfügbar sein müssen, damit er erfolgreich ist. Bei Replikationsfaktor drei und min.insync.replicas=2 kann das Topic einen nicht verfügbaren Broker tolerieren. Wenn nur noch ein synchronisiertes Replikat übrig ist, sollte Kafka starke Schreibvorgänge ablehnen, anstatt Daten mit zu wenigen sicheren Kopien zu akzeptieren.

Aufbewahrungseinstellungen legen fest, wann Kafka alte Log-Segmente löschen kann. Die zeitbasierte Aufbewahrung wird auf Topic-Ebene durch retention.ms gesteuert. Die größenbasierte Aufbewahrung wird durch retention.bytes gesteuert. Ältere Broker-Level-Namen wie log.retention.ms sind Broker-Standardwerte; die Topic-Konfiguration verwendet üblicherweise retention.ms.

Um beispielsweise ein Topic sieben Tage lang aufzubewahren:

kafka-configs.sh --alter   --bootstrap-server broker1:9092   --entity-type topics   --entity-name user-events.v1   --add-config retention.ms=604800000

Um den Speicher pro Partition zu begrenzen, verwenden Sie retention.bytes:

kafka-configs.sh --alter   --bootstrap-server broker1:9092   --entity-type topics   --entity-name user-events.v1   --add-config retention.bytes=10737418240

Denken Sie daran, dass retention.bytes normalerweise pro Partition gilt, nicht für die gesamte Topic-Größe. Ein Topic mit zwölf Partitionen und retention.bytes=10GB kann etwa 120GB vor Replikation und etwa 360GB mit Replikationsfaktor drei verbrauchen. Dies ist die Art von Detail, die überraschende Festplattenwarnungen verursacht.

Kafka löscht Daten nach Log-Segmenten, nicht Datensatz für Datensatz. Wenn Sie eine kurze Aufbewahrungsdauer, aber große Segmente festlegen, erfolgt die Löschung möglicherweise nicht genau zu dem Zeitpunkt, den Sie erwarten. Segmenteinstellungen wie segment.bytes und segment.ms beeinflussen, wann Kafka zu einem neuen Segment wechselt, und nur geschlossene Segmente sind für die Löschung oder Kompaktierung geeignet. Kleinere Segmente können die Bereinigung reaktionsschneller machen, erhöhen aber den Overhead.

cleanup.policy legt fest, was Kafka mit alten Daten macht. Der Standardwert ist delete, der alte Segmente basierend auf der Aufbewahrung entfernt. compact behält den neuesten Datensatz für jeden Schlüssel und entfernt schließlich ältere Datensätze mit demselben Schlüssel. Sie können auch delete,compact für Topics verwenden, die Kompaktierung plus ein Aufbewahrungsfenster benötigen.

Kompaktierung ist nützlich für zustandsähnliche Streams: Benutzerprofilaktualisierungen, Feature-Flag-Werte, Kontoeinstellungen oder Datenbankänderungsereignisse, die nach Primärschlüssel gruppiert sind. Es ist eine schlechte Wahl für Ereignisverläufe, bei denen jedes Ereignis zählt. Wenn Sie ein Audit-Protokoll kompaktieren, können ältere Ereignisse für denselben Schlüssel schließlich verschwinden. Das könnte für Compliance oder Debugging genau falsch sein.

Kompaktierung hängt auch von Schlüsseln ab. Ein kompaktiertes Topic mit null oder inkonsistenten Schlüsseln verhält sich nicht wie ein sauberer Schlüssel-Wert-Änderungsprotokoll. Wenn Producer Benutzeraktualisierungen manchmal mit user_id und manchmal mit E-Mail als Schlüssel senden, sieht Kafka unterschiedliche Schlüssel. Es kann nicht ableiten, dass sie denselben Benutzer repräsentieren.

Komprimierung kann von Produzenten eingestellt werden, und ein Topic kann compression.type definieren, um das Broker-Verhalten zu steuern. Übliche Werte sind producer, gzip, snappy, lz4 und zstd, abhängig von der Kafka-Version. Viele Teams belassen das Topic bei producer und standardisieren die Producer-Komprimierung. lz4 und zstd sind übliche Wahlmöglichkeiten, aber die richtige Antwort hängt vom CPU-Budget, der Nachrichtenform und dem Netzwerkdruck ab.

Sie können die Topic-Konfiguration wie folgt überprüfen:

kafka-configs.sh --describe   --bootstrap-server broker1:9092   --entity-type topics   --entity-name user-events.v1

Und die Partitionsplatzierung wie folgt überprüfen:

kafka-topics.sh --describe   --bootstrap-server broker1:9092   --topic user-events.v1

Verwenden Sie beide Befehle. Topic-Konfigurationen zeigen Ihnen Aufbewahrung, Kompaktierung und ISR-Regeln. Die Topic-Beschreibung zeigt Ihnen Leader, Replikate und den ISR-Status. Ein Topic kann eine perfekte Konfiguration haben und dennoch ungesund sein, weil Replikate nicht synchron sind.

Einige Änderungen sind einfach. Aufbewahrung, Kompaktierungsrichtlinie, min.insync.replicas und mehrere andere Topic-Konfigurationen können dynamisch geändert werden. Einige Änderungen erfordern mehr Vorsicht. Sie können die Partitionsanzahl erhöhen, aber Sie können sie nicht sicher mit einem einfachen Befehl verringern. Das Erhöhen der Partitionen ändert auch die Schlüsselverteilung für zukünftige Datensätze, da die Partitionierungsberechnung mehr Zielpartitionen hat. Vorhandene Datensätze bleiben, wo sie sind; neue Datensätze für denselben Schlüssel können nach der Erhöhung je nach Partitioner in eine andere Partition gelangen. Wenn eine strenge Reihenfolge pro Schlüssel über die Änderung hinweg wichtig ist, planen Sie sorgfältig.

Änderungen des Replikationsfaktors sind operative Arbeit. Das Erhöhen von Replikaten für ein bestehendes Topic bedeutet, dass Kafka vorhandene Daten auf neue Broker kopieren muss. Das kann viel I/O sein. Verwenden Sie das Neuzuweisungstool, überwachen Sie den Fortschritt und drosseln Sie bei Bedarf. Starten Sie keine große Neuzuweisung während der Spitzenlast, es sei denn, Sie wissen bereits, dass der Cluster genügend freie Kapazität hat.

Für ein normales Produktionsereignis-Topic könnte ein praktischer Ausgangspunkt so aussehen:

kafka-topics.sh --create   --bootstrap-server broker1:9092   --topic payments-authorized.v1   --partitions 24   --replication-factor 3   --config min.insync.replicas=2   --config retention.ms=1209600000   --config cleanup.policy=delete

Das bedeutet: genügend Partitionen für Parallelität, drei Kopien für Verfügbarkeit, zwei synchronisierte Replikate erforderlich für starke Schreibvorgänge, vierzehn Tage Aufbewahrung und keine Kompaktierung, da jedes Zahlungsautorisierungsereignis zählt.

Für ein Zustands-Topic ist die Form anders:

kafka-topics.sh --create   --bootstrap-server broker1:9092   --topic user-preferences.v1   --partitions 12   --replication-factor 3   --config min.insync.replicas=2   --config cleanup.policy=compact

Dieses Topic sollte nach Benutzer-ID gruppiert sein. Verbraucher, die den Zustand neu aufbauen, können das kompaktierte Protokoll lesen und schließlich den neuesten Wert für jeden Benutzer sehen. Sie sollten nicht erwarten, dass jede historische Präferenzänderung für immer erhalten bleibt.

Die beste Topic-Konfiguration ist langweilig zu betreiben. Sie hat genügend Partitionen, aber nicht Tausende ohne Grund. Sie hat eine Replikation, die dem Wert der Daten entspricht. Sie hat eine Aufbewahrung, die den Wiederherstellungs- und Compliance-Anforderungen entspricht. Sie verwendet Kompaktierung nur, wenn Schlüssel sinnvoll sind. Sie ist in Code oder Dokumentation beschrieben, sodass ein anderer Ingenieur sie ohne Raten neu erstellen kann.

Eine nützliche Überprüfungsgewohnheit ist es, die Verbrauchergeschichte aufzuschreiben, bevor Sie Topic-Einstellungen auswählen. Wer liest dieses Topic? Müssen sie von Anfang an wiederholen? Wie lange würde ein vollständiger Wiederaufbau dauern? Kann das Quellsystem alte Daten erneut veröffentlichen? Wenn ein Verbraucher drei Tage lang ausfällt, sollte Kafka dann noch die verpassten Datensätze haben? Diese Antworten treiben die Aufbewahrung ehrlicher an als eine standardmäßige Sieben-Tage-Einstellung.

Betrachten Sie einen Betrugserkennungsverbraucher, der Zahlungsereignisse liest. Wenn er sechs Stunden lang ausfällt, möchten Sie mit ziemlicher Sicherheit, dass er von Kafka aufholt. Wenn er dreißig Tage lang ausfällt, erwarten Sie möglicherweise einen separaten Backfill-Prozess aus der Zahlungsdatenbank. Dieses Topic benötigt möglicherweise zwei Wochen Aufbewahrung, nicht für immer. Ein Sicherheits-Audit-Topic kann eine andere Anforderung haben, vielleicht das Verschieben in den Objektspeicher für die langfristige Aufbewahrung, während Kafka nur das heiße Wiederholungsfenster behält.

Die Nachrichtengröße gehört auch in die Topic-Diskussion. Kafka kann größere Datensätze verarbeiten, wenn es entsprechend konfiguriert ist, aber große Nachrichten wirken sich auf Producer, Broker, Verbraucher, Replikation und Fetch-Speicher aus. Wenn Teams beginnen, Multi-Megabyte-JSON-Blobs oder codierte Dateien in ein Topic zu legen, erhöhen Sie nicht nur max.message.bytes und machen weiter. Fragen Sie, ob die Nutzlast in den Objektspeicher mit einem Verweis in Kafka gehört. Kafka ist normalerweise am besten darin, Ereignisse zu bewegen, nicht als Blob-Speicher zu fungieren.

Schemaentwicklung ist keine Topic-Konfigurationseinstellung, aber sie prägt das Topic-Design. Ein Topic, das mit einem Versionssuffix benannt ist, wie orders.v1, gibt Ihnen eine Ausweichmöglichkeit, wenn eine bahnbrechende Änderung unvermeidbar ist. Kompatible Änderungen können im selben Topic bleiben, wenn Verbraucher und Produzenten einer Schema-Richtlinie folgen. Bahnbrechende Änderungen sollten nicht in dasselbe Topic eingeschleust werden, nur weil ein Team den Producer kontrolliert. Kafka entkoppelt Systeme, aber nur, wenn der Vertrag eingehalten wird.

Dokumentieren Sie schließlich das Topic-Eigentum. Jedes Produktionstopic sollte ein besitzendes Team, erwartete Produzenten, erwartete Verbraucher, Aufbewahrungsgrund und Hinweise zur Datensensitivität haben. Das klingt administrativ, bis die Festplatte um 02:00 Uhr voll ist und niemand weiß, ob ein Topic gekürzt, gelöscht, kompaktiert oder gedrosselt werden kann. Eine gute Topic-Konfiguration ist teils technisch und teils operatives Gedächtnis.

Eine letzte Überprüfung vor der Veröffentlichung eines Topics ist das Durchspielen eines Ausfallszenarios. Wenn ein Broker verschwindet, können Produzenten dann noch schreiben? Wenn eine Verbrauchergruppe über das Wochenende ausfällt, deckt die Aufbewahrung dann die Lücke? Wenn ein Produzent schlechte Daten sendet, können Verbraucher dann sicher überspringen, unter Quarantäne stellen oder wiederholen? Wenn das Topic doppelt so schnell wächst wie erwartet, welche Grenze schützt den Cluster: Aufbewahrungszeit, Aufbewahrungsbytes, Kontingente oder ein Alarm?

Kontingente sind erwähnenswert, da die Topic-Konfiguration allein einen gemeinsam genutzten Cluster nicht vor einem lauten Produzenten schützt. Kafka unterstützt Client-Kontingente, die Produktions- und Abrufraten begrenzen können. Wenn mehrere Teams einen Cluster gemeinsam nutzen, können Kontingente eine versehentliche Wiederholung oder einen außer Kontrolle geratenen Produzenten davon abhalten, Broker zu überlasten. Sie sollten mit Alarmen gepaart werden, damit Teams wissen, dass sie gedrosselt werden, anstatt stillschweigend Kafka die Schuld zu geben.

Vergessen Sie nicht die Löschrichtlinie. Einige Cluster deaktivieren das Löschen von Topics auf Broker-Ebene, um Unfälle zu verhindern. Das kann sinnvoll sein, bedeutet aber, dass verlassene Topics durch einen kontrollierten Bereinigungsprozess behandelt werden müssen. Eine monatliche oder vierteljährliche Topic-Bestandsprüfung kann eine überraschende Menge an Festplattenspeicher freigeben, insbesondere in Entwicklungs- und Staging-Clustern, in denen Experimente alte Topics hinterlassen.