Kapitel 1. Einführung in die zustandsorientierte Stromverarbeitung

Diese Arbeit wurde mithilfe von KI übersetzt. Wir freuen uns über dein Feedback und deine Kommentare: translation-feedback@oreilly.com

Apache Flink ist ein verteilter Stream-Prozessor mit intuitiven und ausdrucksstarken APIs zur Implementierung zustandsabhängiger Stream-Processing-Anwendungen. Er führt solche Anwendungen effizient und fehlertolerant in großem Maßstab aus. Flink trat der Apache Software Foundation im April 2014 als Inkubationsprojekt bei und wurde im Januar 2015 zu einem Top-Level-Projekt. Seit seinen Anfängen hat Flink eine sehr aktive und ständig wachsende Gemeinschaft von Nutzern und Mitwirkenden. Bis heute haben mehr als fünfhundert Personen an Flink mitgewirkt, und es hat sich zu einer der ausgereiftesten Open-Source-Stream-Processing-Engines entwickelt, wie die weite Verbreitung beweist. Flink ist die Grundlage für umfangreiche, geschäftskritische Anwendungen in vielen Firmen und Unternehmen in verschiedenen Branchen und auf der ganzen Welt.

Die Stream-Processing-Technologie wird bei großen und kleinen Unternehmen immer beliebter, weil sie für viele etablierte Anwendungsfälle wie Datenanalyse, ETL und transaktionale Anwendungen hervorragende Lösungen bietet, aber auch neue Anwendungen, Softwarearchitekturen und Geschäftsmöglichkeiten ermöglicht. In diesem Kapitel erörtern wir, warum die zustandsorientierte Datenstromverarbeitung so populär geworden ist, und bewerten ihr Potenzial. Wir beginnen mit einem Überblick über herkömmliche Datenanwendungsarchitekturen und weisen auf ihre Grenzen hin. Anschließend stellen wir Anwendungsdesigns vor, die auf Stateful Stream Processing basieren und viele interessante Eigenschaften und Vorteile gegenüber herkömmlichen Ansätzen aufweisen. Schließlich gehen wir kurz auf die Entwicklung von Open-Source-Stream-Prozessoren ein und helfen dir, eine Streaming-Anwendung auf einer lokalen Flink-Instanz auszuführen.

Traditionelle Dateninfrastrukturen

Daten und Datenverarbeitung sind in Unternehmen schon seit vielen Jahrzehnten allgegenwärtig. Im Laufe der Jahre hat die Sammlung und Nutzung von Daten stetig zugenommen, und die Unternehmen haben Infrastrukturen entwickelt und aufgebaut, um diese Daten zu verwalten. Die traditionelle Architektur, die die meisten Unternehmen einsetzen, unterscheidet zwei Arten der Datenverarbeitung: die Transaktionsverarbeitung und die analytische Verarbeitung. In diesem Abschnitt gehen wir auf beide Arten ein und erläutern, wie sie Daten verwalten und verarbeiten.

Transaktionsverarbeitung

Unternehmen nutzen alle Arten von Anwendungen für ihre täglichen Geschäftsaktivitäten, z. B. ERP-Systeme (Enterprise Resource Planning), CRM-Software (Customer Relationship Management) und webbasierte Anwendungen. Diese Systeme sind in der Regel mit getrennten Ebenen für die Datenverarbeitung (die Anwendung selbst) und die Speicherung der Daten (ein transaktionales Datenbanksystem) konzipiert, wie in Abbildung 1-1 dargestellt.

Abbildung 1-1. Traditioneller Aufbau von Transaktionsanwendungen, die Daten in einem entfernten Datenbanksystem speichern

Anwendungen sind in der Regel mit externen Diensten verbunden oder stehen menschlichen Nutzern gegenüber und verarbeiten kontinuierlich eingehende Ereignisse wie Bestellungen, E-Mails oder Klicks auf einer Website. Wenn ein Ereignis verarbeitet wird, liest eine Anwendung seinen Status oder aktualisiert ihn, indem sie Transaktionen gegen das entfernte Datenbanksystem ausführt. Oft bedient ein Datenbanksystem mehrere Anwendungen, die manchmal auf dieselben Datenbanken oder Tabellen zugreifen.

Dieses Anwendungsdesign kann zu Problemen führen, wenn Anwendungen weiterentwickelt oder skaliert werden müssen. Da mehrere Anwendungen möglicherweise mit derselben Datendarstellung arbeiten oder dieselbe Infrastruktur nutzen, erfordert die Änderung des Schemas einer Tabelle oder die Skalierung eines Datenbanksystems eine sorgfältige Planung und viel Aufwand. Ein neuerer Ansatz, um die enge Bündelung von Anwendungen zu überwinden, ist das Microservices-Designmuster. Microservices sind als kleine, in sich geschlossene und unabhängige Anwendungen konzipiert. Sie folgen der UNIX-Philosophie, die besagt, dass man nur eine einzige Aufgabe erfüllen muss, und zwar eine gute. Komplexere Anwendungen werden erstellt, indem mehrere Microservices miteinander verbunden werden, die nur über standardisierte Schnittstellen wie RESTful HTTP-Verbindungen kommunizieren. Da Microservices streng voneinander entkoppelt sind und nur über klar definierte Schnittstellen kommunizieren, kann jeder Microservice mit einem anderen Technologie-Stack implementiert werden, einschließlich einer Programmiersprache, Bibliotheken und Datenspeichern. Microservices und die gesamte benötigte Software und Dienste werden in der Regel in unabhängigen Containern gebündelt und bereitgestellt. Abbildung 1-2 zeigt eine Microservice-Architektur.

Abbildung 1-2. Eine Microservices-Architektur

Analytische Verarbeitung

Die Daten, die in den verschiedenen transaktionalen Datenbanksystemen eines Unternehmens gespeichert sind, können wertvolle Einblicke in den Geschäftsbetrieb eines Unternehmens liefern. Die Daten eines Auftragsbearbeitungssystems können zum Beispiel analysiert werden, um das Umsatzwachstum im Laufe der Zeit zu ermitteln, Gründe für verspätete Lieferungen zu finden oder zukünftige Umsätze vorherzusagen, um den Bestand anzupassen. Transaktionsdaten sind jedoch oft über mehrere unverbundene Datenbanksysteme verteilt und sind wertvoller, wenn sie gemeinsam analysiert werden können. Außerdem müssen die Daten oft in ein gemeinsames Format umgewandelt werden.

Anstatt analytische Abfragen direkt auf den transaktionalen Datenbanken auszuführen, werden die Daten in der Regel in ein Data Warehouse ( ) repliziert, einen speziellen Datenspeicher für analytische Abfrage-Workloads. Um ein Data Warehouse zu befüllen, müssen die von den transaktionalen Datenbanksystemen verwalteten Daten in das Data Warehouse kopiert werden. Der Prozess des Kopierens von Daten in das Data Warehouse wird extract-transform-load (ETL) genannt. Ein ETL-Prozess extrahiert Daten aus einer transaktionalen Datenbank, wandelt sie in eine gemeinsame Darstellung um, die Validierung, Wertnormalisierung, Kodierung, Deduplizierung und Schematransformation umfassen kann, und lädt sie schließlich in die analytische Datenbank. ETL-Prozesse können recht komplex sein und erfordern oft technisch ausgefeilte Lösungen, um die Leistungsanforderungen zu erfüllen. ETL-Prozesse müssen regelmäßig durchgeführt werden, damit die Daten im Data Warehouse synchronisiert werden.

Sobald die Daten in das Data Warehouse importiert worden sind, können sie abgefragt und analysiert werden. In der Regel gibt es zwei Arten von Abfragen, die in einem Data Warehouse ausgeführt werden. Die erste Art sind periodische Berichtsabfragen, die geschäftsrelevante Statistiken wie Umsatz, Nutzerwachstum oder Produktionsleistung berechnen. Diese Kennzahlen werden in Berichten zusammengefasst, die dem Management helfen, den Gesamtzustand des Unternehmens zu beurteilen. Die zweite Art sind Ad-hoc-Abfragen, die darauf abzielen, Antworten auf bestimmte Fragen zu geben und geschäftskritische Entscheidungen zu unterstützen, z. B. eine Abfrage zur Erfassung von Umsatzzahlen und Ausgaben für Radiowerbung, um die Wirksamkeit einer Marketingkampagne zu bewerten. Beide Arten von Abfragen werden von einem Data Warehouse im Stapelverarbeitungsmodus ausgeführt, wie in Abbildung 1-3 dargestellt.

Abbildung 1-3. Eine traditionelle Data-Warehouse-Architektur für Datenanalysen

Die Komponenten des Apache Hadoop-Ökosystems sind heute fester Bestandteil der IT-Infrastrukturen vieler Unternehmen. Anstatt alle Daten in ein relationales Datenbanksystem einzugeben, werden große Datenmengen wie Logdateien, soziale Medien oder Webklickprotokolle in Hadoops verteiltes Dateisystem (HDFS), S3 oder andere Massendatenspeicher wie Apache HBase geschrieben, die große Speicherkapazitäten zu geringen Kosten bieten. Daten, die sich in solchen Speichern befinden, können mit einer SQL-on-Hadoop-Engine, z. B. Apache Hive, Apache Drill oder Apache Impala, abgefragt und verarbeitet werden. Die Infrastruktur bleibt jedoch im Grunde dieselbe wie bei einer traditionellen Data Warehouse-Architektur.

Stateful Stream Processing

Praktisch werden alle Daten als kontinuierliche Ströme von Ereignissen erzeugt. Denk an Benutzerinteraktionen auf Websites oder in mobilen Apps, Bestellungen, Serverprotokolle oder Sensormessungen - all das sind Ströme von Ereignissen. Tatsächlich ist es schwierig, Beispiele für endliche, vollständige Datensätze zu finden, die alle auf einmal erzeugt werden. Die zustandsbehaftete Datenstromverarbeitung ist ein Anwendungsdesignmuster für die Verarbeitung unbegrenzter Ereignisströme und lässt sich auf viele verschiedene Anwendungsfälle in der IT-Infrastruktur eines Unternehmens anwenden. Bevor wir auf die Anwendungsfälle eingehen, erklären wir kurz, wie Stateful Stream Processing funktioniert.

Jede Anwendung, die einen Strom von Ereignissen verarbeitet und nicht nur triviale Record-at-a-time-Transformationen durchführt, muss zustandsorientiert sein und die Möglichkeit haben, Zwischendaten zu speichern und darauf zuzugreifen. Wenn eine Anwendung ein Ereignis empfängt, kann sie beliebige Berechnungen durchführen, die das Lesen von Daten aus dem Zustand oder das Schreiben von Daten in den Zustand beinhalten. Im Prinzip kann der Status an vielen verschiedenen Orten gespeichert und abgerufen werden, z. B. in Programmvariablen, lokalen Dateien oder eingebetteten oder externen Datenbanken.

Apache Flink speichert den Anwendungsstatus lokal im Speicher oder in einer eingebetteten Datenbank. Da es sich bei Flink um ein verteiltes System handelt, muss der lokale Status vor Ausfällen geschützt werden, um Datenverluste im Falle eines Anwendungs- oder Maschinenausfalls zu vermeiden. Flink gewährleistet dies, indem es regelmäßig einen konsistenten Checkpoint des Anwendungsstatus in eine entfernte und dauerhafte Speicherung schreibt. Zustand, Zustandskonsistenz und der Checkpointing-Mechanismus von Flink werden in den folgenden Kapiteln ausführlicher behandelt.

Abbildung 1-4. Eine zustandsabhängige Streaming-Anwendung

Stateful Stream Processing Anwendungen nehmen ihre eingehenden Ereignisse oft aus einem Ereignisprotokoll auf. Ein Ereignisprotokoll speichert und verteilt Ereignisströme. Die Ereignisse werden in ein dauerhaftes, nur anhängendes Protokoll geschrieben, was bedeutet, dass die Reihenfolge der geschriebenen Ereignisse nicht geändert werden kann. Ein Stream, der in ein Ereignisprotokoll geschrieben wird, kann viele Male von denselben oder verschiedenen Verbrauchern gelesen werden. Aufgrund der Append-Only-Eigenschaft des Protokolls werden die Ereignisse immer in genau der gleichen Reihenfolge an alle Verbraucher veröffentlicht. Es gibt mehrere Event-Log-Systeme als Open-Source-Software, von denen Apache Kafka das bekannteste ist, oder als integrierte Dienste, die von Cloud-Computing-Providern angeboten werden.

Die Verbindung einer zustandsbehafteten Streaming-Anwendung, die auf Flink läuft, mit einem Eventlog ist aus mehreren Gründen interessant. In dieser Architektur speichert das Ereignisprotokoll die Eingangsereignisse und kann sie in deterministischer Reihenfolge wiedergeben. Im Falle eines Ausfalls stellt Flink eine Stateful-Streaming-Anwendung wieder her, indem es ihren Zustand von einem früheren Checkpoint wiederherstellt und die Leseposition im Eventlog zurücksetzt. Die Anwendung gibt die Eingangsereignisse aus dem Ereignisprotokoll wieder (und spult sie vor), bis sie das Ende des Streams erreicht. Diese Technik wird verwendet, um Fehler zu beheben, kann aber auch genutzt werden, um eine Anwendung zu aktualisieren, Fehler zu beheben und zuvor ausgegebene Ergebnisse zu reparieren, eine Anwendung auf einen anderen Cluster zu migrieren oder A/B-Tests mit verschiedenen Anwendungsversionen durchzuführen.

Wie bereits erwähnt, ist Stateful Stream Processing eine vielseitige und flexible Architektur, die für viele verschiedene Anwendungsfälle genutzt werden kann. Im Folgenden stellen wir drei Klassen von Anwendungen vor, die häufig mit Stateful Stream Processing implementiert werden: (1) ereignisgesteuerte Anwendungen, (2) Datenpipeline-Anwendungen und (3) Datenanalyseanwendungen.

Reale Streaming-Anwendungsfälle und -Einsätze

Wenn du mehr über reale Anwendungsfälle und Einsätze erfahren möchtest, schau dir die Powered By-Seite von Apache Flink sowie die Vortragsaufzeichnungen und Foliendateien der Flink Forward-Präsentationen an.

Wir beschreiben die Anwendungsklassen als unterschiedliche Muster, um die Vielseitigkeit der zustandsbehafteten Stream-Verarbeitung hervorzuheben, aber die meisten realen Anwendungen weisen die Eigenschaften von mehr als einer Klasse auf.

Ereignisgesteuerte Anwendungen

Ereignisgesteuerte Anwendungen sind zustandsabhängige Streaming-Anwendungen, die Ereignisströme aufnehmen und die Ereignisse mit anwendungsspezifischer Geschäftslogik verarbeiten. Je nach Geschäftslogik kann eine ereignisgesteuerte Anwendung Aktionen auslösen, wie z. B. das Senden einer Warnung oder einer E-Mail, oder Ereignisse in einen ausgehenden Ereignisstrom schreiben, der von einer anderen ereignisgesteuerten Anwendung genutzt wird.

Typische Anwendungsfälle für ereignisgesteuerte Anwendungen sind:

  • Echtzeit-Empfehlungen (z. B. für Produktempfehlungen, während Kunden auf der Website eines Einzelhändlers stöbern)

  • Mustererkennung oder komplexe Ereignisverarbeitung (z. B. zur Betrugserkennung bei Kreditkartentransaktionen)

  • Erkennung von Anomalien (z. B. zur Erkennung von Versuchen, in ein Computernetzwerk einzudringen)

Ereignisgesteuerte Anwendungen sind eine Weiterentwicklung der Microservices. Sie kommunizieren über Ereignisprotokolle statt über REST-Aufrufe und speichern Anwendungsdaten als lokalen Zustand, anstatt sie in einen externen Datenspeicher wie eine relationale Datenbank oder einen Key-Value-Store zu schreiben und von dort zu lesen. Abbildung 1-5 zeigt eine Service-Architektur, die aus ereignisgesteuerten Streaming-Anwendungen besteht.

Abbildung 1-5. Eine ereignisgesteuerte Anwendungsarchitektur

Die Anwendungen in Abbildung 1-5 sind durch Ereignisprotokolle verbunden. Eine Anwendung sendet ihre Ausgaben in ein Ereignisprotokoll und eine andere Anwendung konsumiert die Ereignisse, die die andere Anwendung gesendet hat. Das Ereignisprotokoll entkoppelt Sender und Empfänger und ermöglicht eine asynchrone, nicht blockierende Ereignisübertragung. Jede Anwendung kann zustandsabhängig sein und ihren eigenen Zustand lokal verwalten, ohne auf externe Datenspeicher zuzugreifen. Die Anwendungen können auch einzeln betrieben und skaliert werden.

Ereignisgesteuerte Anwendungen bieten im Vergleich zu transaktionalen Anwendungen oder Microservices mehrere Vorteile. Der lokale Zugriff auf den Status bietet eine sehr gute Leistung im Vergleich zum Lesen und Schreiben von Abfragen auf entfernten Datenspeichern. Skalierung und Fehlertoleranz werden vom Stream-Prozessor übernommen, und durch die Nutzung eines Ereignisprotokolls als Eingabequelle wird die gesamte Eingabe einer Anwendung zuverlässig gespeichert und kann deterministisch wiedergegeben werden. Außerdem kann Flink den Zustand einer Anwendung auf einen früheren Speicherpunkt zurücksetzen, sodass eine Anwendung weiterentwickelt oder skaliert werden kann, ohne ihren Zustand zu verlieren.

Ereignisgesteuerte Anwendungen stellen ziemlich hohe Anforderungen an den Stream-Prozessor, auf dem sie ausgeführt werden. Nicht alle Stream-Prozessoren sind für die Ausführung ereignisgesteuerter Anwendungen gleich gut geeignet. Die Ausdruckskraft der API und die Qualität der Zustandsbehandlung und der Ereigniszeitunterstützung bestimmen die Geschäftslogik, die implementiert und ausgeführt werden kann. Dieser Aspekt hängt von den APIs des Stream-Prozessors ab, von der Art der Zustandsprimitive, die er bietet, und von der Qualität seiner Unterstützung für die Ereigniszeitverarbeitung. Darüber hinaus sind die einmalige Zustandskonsistenz und die Skalierbarkeit einer Anwendung grundlegende Anforderungen für ereignisgesteuerte Anwendungen. Apache Flink erfüllt all diese Kriterien und ist eine sehr gute Wahl für diese Art von Anwendungen.

Daten-Pipelines

Die heutigen IT-Architekturen umfassen viele verschiedene Datenspeicher, wie relationale und spezielle Datenbanksysteme, Ereignisprotokolle, verteilte Dateisysteme, In-Memory-Caches und Suchindizes. Alle diese Systeme speichern Daten in unterschiedlichen Formaten und Datenstrukturen, die für das jeweilige Zugriffsmuster die beste Leistung bieten. Es ist üblich, dass Unternehmen dieselben Daten in mehreren verschiedenen Systemen speichern, um die Leistung der Datenzugriffe zu verbessern. Zum Beispiel können Informationen zu einem Produkt, das in einem Webshop angeboten wird, in einer Transaktionsdatenbank, einem Web-Cache und einem Suchindex gespeichert werden. Durch diese Replikation der Daten müssen die Datenspeicher synchron gehalten werden.

Ein traditioneller Ansatz, um Daten in verschiedenen Speichern zu synchronisieren, sind periodische ETL-Aufträge. Diese erfüllen jedoch nicht die Latenzanforderungen für viele der heutigen Anwendungsfälle. Eine Alternative ist die Verwendung eines Ereignisprotokolls für die Verteilung von Aktualisierungen. Die Aktualisierungen werden in das Ereignisprotokoll geschrieben und von diesem verteilt. Die Verbraucher des Protokolls übernehmen die Aktualisierungen in die betroffenen Datenspeicher. Je nach Anwendungsfall müssen die übertragenen Daten normalisiert, mit externen Daten angereichert oder aggregiert werden, bevor sie in den Zieldatenspeicher übernommen werden.

Das Einlesen, Umwandeln und Einfügen von Daten mit geringer Latenz ist ein weiterer häufiger Anwendungsfall für zustandsabhängige Stream Processing-Anwendungen. Diese Art von Anwendung wird als Datenpipeline bezeichnet. Datenpipelines müssen in der Lage sein, große Datenmengen in kurzer Zeit zu verarbeiten. Ein Stream-Prozessor, der eine Datenpipeline betreibt, sollte außerdem über viele Source- und Sink-Konnektoren verfügen, um Daten von verschiedenen Speichersystemen zu lesen und in diese zu schreiben. Auch das alles kann Flink.

Streaming-Analytik

ETL-Aufträge importieren in regelmäßigen Abständen Daten in einen Datenspeicher und die Daten werden durch Ad-hoc- oder geplante Abfragen verarbeitet. Dabei handelt es sich um Stapelverarbeitung, unabhängig davon, ob die Architektur auf einem Data Warehouse oder Komponenten des Hadoop-Ökosystems basiert. Das regelmäßige Laden von Daten in ein Datenanalysesystem ist zwar seit vielen Jahren Stand der Technik, führt aber zu erheblichen Latenzzeiten in der Analysepipeline.

Je nach den Zeitplanungsintervallen kann es Stunden oder Tage dauern, bis ein Datenpunkt in einen Bericht aufgenommen wird. Bis zu einem gewissen Grad kann die Latenzzeit durch den Import von Daten in den Datenspeicher mit einer Datenpipeline-Anwendung verringert werden. Aber auch bei kontinuierlichem ETL wird es immer eine Verzögerung geben, bis ein Ereignis von einer Abfrage verarbeitet wird. Während diese Verzögerung in der Vergangenheit akzeptabel war, müssen Anwendungen heute in der Lage sein, Daten in Echtzeit zu sammeln und sofort darauf zu reagieren (z. B. indem sie sich an veränderte Bedingungen in einem Handyspiel anpassen oder das Nutzererlebnis für einen Online-Händler personalisieren).

Anstatt darauf zu warten, dass sie regelmäßig ausgelöst wird, nimmt eine Streaming-Analyse-Anwendung kontinuierlich Ereignisströme auf und aktualisiert ihr Ergebnis, indem sie die neuesten Ereignisse mit geringer Latenzzeit einbezieht. Dies ist vergleichbar mit den Wartungstechniken, die Datenbanksysteme zur Aktualisierung von materialisierten Ansichten verwenden. Normalerweise speichern Streaming-Anwendungen ihre Ergebnisse in einem externen Datenspeicher, der effiziente Aktualisierungen unterstützt, z. B. in einer Datenbank oder einem Key-Value-Speicher. Die live aktualisierten Ergebnisse einer Streaming-Analytics-Anwendung können für Dashboard-Anwendungen genutzt werden, wie in Abbildung 1-6 dargestellt.

Abbildung 1-6. Eine Streaming-Analytics-Anwendung

Neben der viel kürzeren Zeit, die benötigt wird, um ein Ereignis in ein Analyseergebnis einfließen zu lassen, gibt es einen weiteren, weniger offensichtlichen Vorteil von Streaming-Analyseanwendungen. Herkömmliche Analysepipelines bestehen aus mehreren Einzelkomponenten wie einem ETL-Prozess, einem Speichersystem und - im Falle einer Hadoop-basierten Umgebung - einem Datenprozessor und einem Zeitplannungsprogramm zum Auslösen von Aufträgen oder Abfragen. Im Gegensatz dazu kümmert sich ein Stream-Prozessor, der eine zustandsabhängige Streaming-Anwendung ausführt, um all diese Verarbeitungsschritte, einschließlich der Aufnahme von Ereignissen, der kontinuierlichen Berechnung einschließlich der Zustandsverwaltung und der Aktualisierung der Ergebnisse. Außerdem kann der Stream-Prozessor Ausfälle mit einer einmaligen Konsistenzgarantie beheben und die Rechenressourcen einer Anwendung anpassen. Stream-Prozessoren wie Flink unterstützen auch die Verarbeitung von Ereignissen, um korrekte und deterministische Ergebnisse zu erzielen, und können große Datenmengen in kurzer Zeit verarbeiten.

Streaming-Analytics-Anwendungen werden häufig für folgende Zwecke eingesetzt:

  • Überwachung der Qualität von Mobilfunknetzen

  • Analyse des Nutzerverhaltens in mobilen Anwendungen

  • Ad-hoc-Analyse von Live-Daten in der Verbrauchertechnologie

Auch wenn wir es hier nicht behandeln, bietet Flink auch Unterstützung für analytische SQL-Abfragen über Streams.

Die Entwicklung von Open Source Stream Processing

Die Datenstromverarbeitung ist keine neue Technologie. Einige der ersten Forschungsprototypen und kommerziellen Produkte gehen auf die späten 1990er Jahre zurück. Die zunehmende Verbreitung der Stream-Processing-Technologie in der jüngeren Vergangenheit wurde jedoch vor allem durch die Verfügbarkeit ausgereifter Open-Source-Stream-Prozessoren vorangetrieben. Heute treiben verteilte Open-Source-Stream-Prozessoren geschäftskritische Anwendungen in vielen Unternehmen verschiedener Branchen an, z. B. im (Online-)Einzelhandel, in den sozialen Medien, in der Telekommunikation, bei Spielen und im Bankwesen. Open-Source-Software ist eine wichtige Triebfeder für diesen Trend, vor allem aus zwei Gründen:

  1. Open-Source-Stream-Processing-Software ist eine Ware, die jeder bewerten und nutzen kann.
  2. Die skalierbare Stream-Processing-Technologie entwickelt sich dank der Bemühungen vieler Open-Source-Communities schnell weiter.

Allein die Apache Software Foundation beherbergt mehr als ein Dutzend Projekte zum Thema Stream Processing. Neue Projekte zur verteilten Datenstromverarbeitung betreten kontinuierlich die Open-Source-Bühne und fordern den Stand der Technik mit neuen Funktionen und Möglichkeiten heraus. Die Open-Source-Gemeinschaften verbessern ständig die Fähigkeiten ihrer Projekte und verschieben die technischen Grenzen der Streamverarbeitung. Wir werfen einen kurzen Blick in die Vergangenheit, um zu sehen, woher die Open-Source-Streamverarbeitung kommt und wo sie heute steht.

Ein bisschen Geschichte

Die erste Generation verteilter Open-Source-Stream-Prozessoren (2011) konzentrierte sich auf die Ereignisverarbeitung mit Latenzen im Millisekundenbereich und bot Garantien gegen den Verlust von Ereignissen bei Ausfällen. Diese Systeme hatten eher einfache APIs und boten keine eingebaute Unterstützung für genaue und konsistente Ergebnisse von Streaming-Anwendungen, da die Ergebnisse vom Timing und der Reihenfolge der ankommenden Ereignisse abhingen. Außerdem konnten Ereignisse, auch wenn sie nicht verloren gingen, mehr als einmal verarbeitet werden. Im Gegensatz zu Batch-Prozessoren tauschten die ersten Open-Source-Stream-Prozessoren die Genauigkeit der Ergebnisse gegen eine bessere Latenzzeit ein. Die Beobachtung, dass Datenverarbeitungssysteme (zu diesem Zeitpunkt) entweder schnelle oder genaue Ergebnisse liefern konnten, führte zur Entwicklung der sogenannten Lambda-Architektur, die in Abbildung 1-7 dargestellt ist.

Abbildung 1-7. Die Lambda-Architektur

Die Lambda-Architektur ergänzt die herkömmliche periodische Batch-Verarbeitungsarchitektur um eine Geschwindigkeitsschicht, die von einem Stream-Prozessor mit niedriger Latenz angetrieben wird. Die Daten, die bei der Lambda-Architektur ankommen, werden vom Stream-Prozessor aufgenommen und in die Stapelspeicherung geschrieben. Der Stream-Prozessor berechnet ungefähre Ergebnisse nahezu in Echtzeit und schreibt sie in eine Geschwindigkeitstabelle. Der Stapelprozessor verarbeitet die Daten in der Stapelspeicherung regelmäßig, schreibt die genauen Ergebnisse in eine Stapeltabelle und löscht die entsprechenden ungenauen Ergebnisse aus der Geschwindigkeitstabelle. Die Anwendungen verbrauchen die Ergebnisse, indem sie die ungefähren Ergebnisse aus der Geschwindigkeitstabelle und die genauen Ergebnisse aus der Stapeltabelle zusammenführen.

Die Lambda-Architektur ist nicht mehr auf dem neuesten Stand der Technik, wird aber immer noch an vielen Stellen eingesetzt. Das ursprüngliche Ziel dieser Architektur war es, die hohe Ergebnislatenz der ursprünglichen Batch-Analytics-Architektur zu verbessern. Sie hat jedoch ein paar bemerkenswerte Nachteile. Erstens erfordert sie zwei semantisch gleichwertige Implementierungen der Anwendungslogik für zwei separate Verarbeitungssysteme mit unterschiedlichen APIs. Zweitens sind die vom Stream-Prozessor berechneten Ergebnisse nur annähernd. Drittens ist die Lambda-Architektur schwer einzurichten und zu pflegen.

Die nächste Generation verteilter Open-Source-Stream-Prozessoren (2013) verbesserte die erste Generation und bot bessere Ausfallgarantien und stellte sicher, dass im Falle eines Fehlers jeder Eingabedatensatz das Ergebnis genau einmal beeinflusst. Außerdem entwickelten sich die Programmier-APIs von eher einfachen Bedienerschnittstellen zu High-Level-APIs mit mehr eingebauten Primitiven. Einige Verbesserungen, wie z. B. ein höherer Durchsatz und bessere Ausfallgarantien, gingen jedoch auf Kosten einer Erhöhung der Verarbeitungslatenz von Millisekunden auf Sekunden. Außerdem waren die Ergebnisse immer noch vom Timing und der Reihenfolge der eintreffenden Ereignisse abhängig.

Die dritte Generation der verteilten Open-Source-Stream-Prozessoren (2015) befasst sich mit der Abhängigkeit der Ergebnisse vom Zeitpunkt und der Reihenfolge der eintreffenden Ereignisse. In Kombination mit der "Exact-once"-Failure-Semantik sind die Systeme dieser Generation die ersten Open-Source-Stream-Prozessoren, die konsistente und genaue Ergebnisse berechnen können. Da diese Systeme nur Ergebnisse berechnen, die auf tatsächlichen Daten basieren, können sie auch historische Daten genauso verarbeiten wie "Live"-Daten. Eine weitere Verbesserung war die Aufhebung des Kompromisses zwischen Latenz und Durchsatz. Während frühere Stream-Prozessoren nur entweder einen hohen Durchsatz oder eine niedrige Latenz bieten, sind die Systeme der dritten Generation in der Lage, beide Enden des Spektrums zu bedienen. Die Stream-Prozessoren dieser Generation haben die Lambda-Architektur überflüssig gemacht.

Zusätzlich zu den bisher besprochenen Systemeigenschaften wie Fehlertoleranz, Leistung und Ergebnisgenauigkeit haben Stream-Prozessoren auch kontinuierlich neue betriebliche Funktionen hinzugefügt, wie z. B. hochverfügbare Setups, enge Integration mit Ressourcenmanagern wie YARN oder Kubernetes und die Fähigkeit, Streaming-Anwendungen dynamisch zu skalieren. Weitere Funktionen sind die Möglichkeit, den Anwendungscode zu aktualisieren oder einen Auftrag auf einen anderen Cluster oder eine neue Version des Stream-Prozessors zu migrieren, ohne den aktuellen Status zu verlieren.

Zusammenfassung

In diesem Kapitel haben wir eine Einführung in die zustandsabhängige Stream-Verarbeitung gegeben, ihre Anwendungsfälle diskutiert und einen ersten Blick auf Apache Flink geworfen. Wir begannen mit einer Zusammenfassung der traditionellen Dateninfrastrukturen, der Art und Weise, wie Geschäftsanwendungen üblicherweise entwickelt werden, und der Art und Weise, wie Daten in den meisten Unternehmen heute gesammelt und analysiert werden. Dann stellten wir die Idee der zustandsorientierten Stream-Verarbeitung vor und erklärten, wie sie ein breites Spektrum von Anwendungsfällen abdeckt, das von Geschäftsanwendungen und Microservices bis hin zu ETL und Datenanalyse reicht. Wir haben erörtert, wie sich Open-Source-Stream-Processing-Systeme seit ihren Anfängen in den frühen 2010er Jahren entwickelt haben und wie Stream-Processing zu einer praktikablen Lösung für viele Anwendungsfälle in heutigen Unternehmen wurde. Zum Schluss haben wir einen Blick auf Apache Flink und seine umfangreichen Funktionen geworfen und gezeigt, wie man ein lokales Flink-Setup installiert und eine erste Stream-Processing-Anwendung ausführt.

1 Die Stapelverarbeitungs-API von Flink, die DataSet-API, und ihre Operatoren sind von ihren entsprechenden Streaming-Pendants getrennt. Die Vision der Flink-Community ist es jedoch, die Batch-Verarbeitung als einen Spezialfall der Stream-Verarbeitung zu behandeln - die Verarbeitung von begrenzten Streams. Die Flink-Gemeinschaft ist bestrebt, Flink zu einem System mit einer wirklich vereinheitlichten Batch- und Streaming-API und -Laufzeit weiterzuentwickeln.

Get Stream Processing mit Apache Flink now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.