# Streamverarbeitung: Architektur wie LEGO-Steine
Moderne Datenverarbeitungssysteme erfordern Flexibilität und Skalierbarkeit. In diesem Artikel zerlegen wir, wie man Kafka, Flink, S3 und andere Komponenten zu einer einheitlichen Streaming-Plattform mit modularen Architekturprinzipien kombiniert. Wir tauchen detailliert in die Integrationsstufen ein, von der Datengenerierung bis zur Echtzeit-Analyse.
Systemgrundlage: Streaming-Plattform
Um Streamverarbeitung aufzubauen, verwenden wir einen Stack aus erprobten Technologien. Die zentrale Komponente ist Apache Kafka – eine verteilte Streaming-Plattform, die zuverlässige Nachrichtenübermittlung gewährleistet. Daneben setzen wir ein:
- Kafka Connect zur Integration mit externen Systemen
- Schema Registry zur Verwaltung von Datenschemata
- Kafka UI als visuelle Verwaltungsoberfläche
Die zentrale Idee ist, Komponenten wie LEGO-Steine zu behandeln. Jede übernimmt eine spezifische Funktion und verbindet sich mit anderen über klar definierte Schnittstellen. Um eine minimale Einrichtung zu starten, reichen Docker Compose und Git LFS. Das System wird über Multi-Stage-Builds zusammengesetzt, was reproduzierbare Umgebungen gewährleistet.
Beispielhafte Basis-Konfiguration in docker-compose.yml:
services:
kafka:
image: confluentinc/cp-kafka:8.1.0
environment:
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
schema-registry:
image: confluentinc/cp-schema-registry:8.1.0
environment:
SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
Es ist wichtig, den Unterschied zwischen traditionellen Datenbanken und Streaming-Systemen zu verstehen. In relationalen DBMS liegt der Fokus auf Zustand (Tabellen, Datensätze), während in der Streamverarbeitung Events im Vordergrund stehen. Jede Nachricht in Kafka stellt ein unveränderliches Event dar, das ans Ende des Logs angehängt wird. Dieser Ansatz ermöglicht Systeme mit garantierter Zustellung und Zustandswiederherstellung.
Stufen der Datenintegration
Wir teilen den Prozess des Systemaufbaus in vier logische Stufen ein:
- Ingest – Empfang von Daten aus externen Quellen
- Storage – persistente Speicherung
- Transform – Transformation und Anreicherung
- Serve – Bereitstellung der Ergebnisse
Ingest: Datengenerierung und -aufnahme
In der Ingest-Stufe konfigurieren wir die Datenquelle über Kafka Connect. Zur Demonstration implementieren wir einen Generator für Temperaturmessungen von Sensoren. Der Java-Connector erzeugt synthetische Daten mit geografischen Koordinaten und Temperatur, unter Berücksichtigung der Tageszeit und der Position relativ zum Äquator.
Connector-Konfiguration:
{
"connector.class": "dev.miron.connect.temp.TempSourceConnector",
"tasks.max": "1",
"topic": "earth-temp",
"sensors": "5",
"messages.per.sensor.per.second": "1"
}
Beachten Sie die Verwendung von Avro zur Serialisierung. Nachrichten werden im binären Format gespeichert, was den Datenverkehr reduziert und die Verarbeitung beschleunigt. Schema Registry kümmert sich um Schema-Versionierung und Kompatibilitätsprüfungen (BACKWARD-Modus). Bei Änderungen der Datenstruktur weist das System ungültige Updates automatisch zurück.
Storage: Langfristige Speicherung
Für persistente Speicherung nutzen wir eine Kombination aus S3 und Apache Iceberg. S3 dient als Objektspeicher, während Iceberg eine Metadatenschicht hinzufügt, die ACID-Transaktionen und Time Travel ermöglicht. Dieser Ansatz bewältigt große Datensätze effizient und vermeidet Probleme traditioneller Dateisysteme.
Sink-Connector-Konfiguration:
{
"connector.class": "io.confluent.connect.s3.S3SinkConnector",
"topics": "earth-temp",
"s3.bucket.name": "data-lake",
"storage.class": "io.confluent.connect.s3.storage.S3Storage",
"format.class": "io.confluent.connect.s3.format.avro.AvroFormat"
}
Für Datenabfragen verwenden wir Trino – einen verteilten SQL-Engine, der Daten aus mehreren Quellen föderieren kann. Das ermöglicht komplexe analytische Abfragen ohne Datenverschiebung.
Daten-Transformation
Wir implementieren die Transform-Stufe mit Apache Flink – einem Stream-Processing-Engine, der Windows und stateful Operations unterstützt. Beispielaufgabe: Umwandlung der Temperatur von Fahrenheit nach Celsius und Filterung anomaler Werte.
DataStream<TempEvent> processed = source
.map(event -> {
event.setCelsius((event.getFahrenheit() - 32) * 5/9);
return event;
})
.filter(event -> event.getCelsius() > -50 && event.getCelsius() < 60);
Flink integriert sich mit Kafka über native Connectoren. Es ist entscheidend, Checkpointing korrekt zu konfigurieren, um Exactly-Once-Verarbeitungs-Garantien zu gewährleistet. Wichtige Parameter:
execution.checkpointing.interval: 60000state.backend: rocksdbstate.checkpoints.dir: file:///checkpoints
Zur Überwachung nutzen wir die integrierte Weboberfläche von Flink, um Verzögerungen (Lag) und Operator-Zustände zu verfolgen.
Service-Ebene
In der finalen Stufe stehen Daten Verbrauchern zur Verfügung. Wir implementieren zwei Optionen:
- PostgreSQL über JDBC-Connector für operative Abfragen
- Redis zum Cachen heißer Daten
PostgreSQL-Sink-Konfiguration:
{
"connector.class": "io.confluent.connect.jdbc.JdbcSinkConnector",
"connection.url": "jdbc:postgresql://postgres:5432/analytics",
"topics": "processed-temp",
"auto.create": "true",
"insert.mode": "upsert",
"pk.fields": "sensorId,timestamp"
}
Für Redis verwenden wir einen benutzerdefinierten Connector, der die neuesten Messwerte für jeden Sensor in Hash-Tabellen speichert. Das liefert Millisekunden-Latenz für Abfragen zu aktuellen Daten.
Wichtige Erkenntnisse
- Datenschemata müssen über Schema Registry mit BACKWARD-Kompatibilität verwaltet werden
- Stateful Processing in Flink erfordert Checkpointing-Einrichtung und Auswahl eines State-Backends
- Systemzerlegung in Ingest/Storage/Transform/Serve-Stufen vereinfacht das Debugging
- Binäre Serialisierung (Avro/Protobuf) ist entscheidend für die Leistung von Streaming-Systemen
- Konfigurationstests über Docker Compose ermöglichen schnelle Iterationen
— Editorial Team
Noch keine Kommentare.