Kapitel 4. Apache Spark als Stream-Processing-Engine

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

In Kapitel 3 haben wir ein allgemeines Architekturdiagramm einer Streaming-Data-Plattform dargestellt und aufgezeigt, wo Spark als verteilte Verarbeitungsmaschine in ein Big-Data-System passt.

Diese Architektur gab uns Aufschluss darüber, was wir in Bezug auf Schnittstellen und Verbindungen zum restlichen Ökosystem zu erwarten haben, zumal wir uns auf die Stream-Datenverarbeitung mit Apache Spark konzentrieren. Die Stream-Verarbeitung, egal ob in ihrer Spark Streaming- oder Structured Streaming-Variante, ist ein weiterer Ausführungsmodus für Apache Spark.

In diesem Kapitel stellen wir dir die wichtigsten Funktionen vor, die Spark als Stream-Processing-Engine auszeichnen.

Das Märchen von den zwei APIs

Wie wir bereits in "Einführung in Apache Spark" erwähnt haben , bietet Spark zwei verschiedene Stream-Processing-APIs, Spark Streaming und Structured Streaming:

Spark Streaming

Bei handelt es sich um eine API und eine Reihe von Konnektoren, in denen ein Spark-Programm kleine Datenstapel aus einem Stream in Form von Mikrostapeln in festen Zeitabständen erhält, eine bestimmte Berechnung durchführt und schließlich in jedem Intervall ein Ergebnis zurückgibt.

Strukturiertes Streaming

Bei handelt es sich um eine API und eine Reihe von Konnektoren, die auf dem Substrat eines SQL-Abfrageoptimierers, Catalyst, aufbauen. Sie bietet eine API, die auf DataFrameund dem Konzept der kontinuierlichen Abfragen über eine unbegrenzte Tabelle basiert, die ständig mit neuen Datensätzen aus dem Stream aktualisiert wird.

Die Schnittstelle, die Spark in diesen Bereichen bietet, ist so umfangreich, dass dieses Buch große Teile der Erklärung dieser beiden Arten der Verarbeitung von Streaming-Datensätzen widmet. Ein wichtiger Punkt ist, dass beide APIs auf den Kernfunktionen von Spark basieren und viele der Low-Level-Funktionen in Bezug auf verteilte Berechnungen, In-Memory-Caching und Cluster-Interaktionen gemeinsam haben.

Im Vergleich zu seinem MapReduce-Vorgänger bietet Spark eine Vielzahl von Operatoren, mit denen der Programmierer komplexe Verarbeitungen wie maschinelles Lernen oder Event-Time-Manipulationen durchführen kann. Wir werden gleich die grundlegenden Eigenschaften genauer untersuchen, die es Spark ermöglichen, dieses Kunststück zu vollbringen.

Wir möchten nur darauf hinweisen, dass diese Schnittstellen genauso einfach gestaltet sind wie ihre Batch-Gegenstücke - die Bedienung einer DStream fühlt sich an wie die Bedienung einer RDD und die Bedienung einer Streaming Dataframe sieht unheimlich aus wie die Bedienung einer Batch-Version.

Apache Spark präsentiert sich als einheitliche Engine, die Entwicklern eine konsistente Umgebung bietet, wenn sie eine Batch- oder eine Streaming-Anwendung entwickeln wollen. In beiden Fällen stehen den Entwicklern die gesamte Leistung und Geschwindigkeit eines verteilten Frameworks zur Verfügung.

Vor dem Einsatz einer vollwertigen Stream-Processing-Anwendung versuchen Programmierer und Analysten zunächst, Erkenntnisse in interaktiven Umgebungen mit einer schnellen Feedbackschleife zu gewinnen. Spark bietet eine integrierte Shell, die auf der Scala REPL (kurz für Read-Eval-Print-Loop) basiert und als Prototyping-Basis verwendet werden kann. Es gibt verschiedene Notebook-Implementierungen wie Zeppelin, Jupyter oder das Spark Notebook, die diese interaktive Erfahrung auf eine benutzerfreundliche Weboberfläche übertragen. Diese Prototyping-Phase ist in den frühen Phasen der Entwicklung unverzichtbar, und das gilt auch für ihre Schnelligkeit.

Wenn du dir das Diagramm in Abbildung 3-1 noch einmal ansiehst, wirst du feststellen, dass das, was wir in dem Diagramm als Ergebnisse bezeichnet haben, umsetzbare Erkenntnisse sind - was oft Umsatz oder Kosteneinsparungen bedeutet -, die jedes Mal entstehen, wenn eine Schleife (die beim geschäftlichen oder wissenschaftlichen Problem beginnt und endet) vollständig durchlaufen wird. Zusammengefasst ist diese Schleife eine grobe Darstellung der experimentellen Methode, die durch Beobachtung, Hypothese, Experiment, Messung, Interpretation und Schlussfolgerung führt.

Apache Spark hat sich bei seinen Streaming-Modulen schon immer dafür entschieden, die kognitive Belastung durch den Wechsel zu einer Streaming-Anwendung sorgfältig zu managen. Darüber hinaus gibt es weitere wichtige Design-Entscheidungen, die sich auf die Fähigkeiten der Stream-Verarbeitung auswirken, angefangen bei der In-Memory Speicherung.

Sparks Speichernutzung

Spark bietet eine In-Memory-Speicherung von Slices eines Datensatzes, die zunächst aus einer Datenquelle geladen werden müssen. Bei der Datenquelle kann es sich um ein verteiltes Dateisystem oder ein anderes Speichermedium handeln. Sparks Form der In-Memory-Speicherung ist mit dem Caching von Daten vergleichbar.

Daher hat ein Wert in der In-Memory Speicherung von Spark eine Basis, die seine anfängliche Datenquelle ist, und Schichten von aufeinanderfolgenden Operationen, die auf ihn angewendet werden.

Wiederherstellung bei Ausfall

Was passiert im Falle eines Ausfalls? Da Spark genau weiß, welche Datenquelle für den Ingest der Daten verwendet wurde, und weil es auch alle Operationen kennt, die bisher darauf ausgeführt wurden, kann es das Segment der verlorenen Daten, das sich auf einem abgestürzten Executor befand, von Grund auf neu aufbauen. Das geht natürlich schneller, wenn diese Wiederherstellung(Recovery, in Sparks Sprache) nicht komplett von Grund auf erfolgen muss. Spark bietet also einen Replikationsmechanismus, ähnlich wie bei verteilten Dateisystemen.

Da Speicher jedoch ein so wertvolles und begrenztes Gut ist, macht Spark den Cache (standardmäßig) kurzlebig.

Faule Bewertung

Wie du unter in späteren Kapiteln noch genauer sehen wirst, wird ein Großteil der Operationen, die für Werte in der Speicherung von Spark definiert werden können, mit einer "lazy" Ausführung versehen, und es ist die Ausführung einer abschließenden, eifrigen Ausgabeoperation, die die eigentliche Ausführung der Berechnung in einem Spark-Cluster auslöst. Es ist erwähnenswert, dass, wenn ein Programm aus einer Reihe von linearen Operationen besteht, wobei die vorherige Operation in die nächste einfließt, die Zwischenergebnisse verschwinden, sobald der nächste Schritt seine Eingabe verbraucht hat.

Cache-Hinweise

andererseits, was passiert, wenn wir mehrere Operationen mit einem einzigen Zwischenergebnis durchführen müssen? Sollen wir es mehrmals berechnen? Glücklicherweise können Benutzer in Spark angeben, dass ein Zwischenwert wichtig ist und wie sein Inhalt für später gesichert werden soll.

Abbildung 4-1 zeigt den Datenfluss eines solchen Vorgangs.

spas 0401
Abbildung 4-1. Operationen mit zwischengespeicherten Werten

Schließlich bietet Spark die Möglichkeit, den Cache auf eine sekundäre Speicherung auszulagern, falls der Speicher im Cluster nicht mehr ausreicht. Damit wird der In-Memory-Betrieb auf eine sekundäre - und deutlich langsamere - Speicherung ausgedehnt, um die funktionalen Aspekte eines Datenprozesses bei vorübergehenden Lastspitzen zu erhalten.

Nachdem wir nun eine Vorstellung von den Hauptmerkmalen von Apache Spark haben, wollen wir uns nun einer Spark-internen Designentscheidung widmen, nämlich dem Kompromiss zwischen Latenz und Durchsatz.

Die Latenzzeit verstehen

Wie wir auf bereits erwähnt haben, entscheidet sich Spark Streaming für Microbatching. Es generiert in einem festen Intervall einen Chunk von Elementen und beginnt nach Ablauf dieses Intervalls mit der Verarbeitung der im letzten Intervall gesammelten Daten. Structured Streaming verfolgt einen etwas anderen Ansatz, indem es das fragliche Intervall so klein wie möglich macht (die Verarbeitungszeit des letzten Microbatch) - und in einigen Fällen auch einen kontinuierlichen Verarbeitungsmodus vorschlägt. Dennoch ist Microbatching heutzutage immer noch der dominierende interne Ausführungsmodus der Stream-Verarbeitung in Apache Spark.

Eine Folge des Microbatching ist, dass jedes Microbatch die Verarbeitung eines bestimmten Elements einer Charge um mindestens die Zeit des Chargenintervalls verzögert.

Erstens erzeugen Mikrobatches eine Basislatenz. Es ist noch nicht klar, wie klein diese Latenz sein kann, aber etwa eine Sekunde ist eine relativ gängige Zahl für die untere Grenze. Für viele Anwendungen ist eine Latenzzeit von einigen Minuten ausreichend, zum Beispiel:

  • Ein Dashboard, das dich über die wichtigsten Leistungsindikatoren deiner Website in den letzten Minuten auf dem Laufenden hält

  • Extrahieren der neuesten Trending Topics in einem sozialen Netzwerk

  • Berechnung der Energieverbrauchstrends einer Gruppe von Haushalten

  • Neue Medien in einem Empfehlungssystem einführen

Während Spark ein Prozessor mit Chancengleichheit ist und alle Datenelemente (höchstens) einen Batch lang verzögert, bevor sie verarbeitet werden, gibt es einige andere Streaming-Engines, die einige Elemente, die Priorität haben, schneller verarbeiten können und damit eine schnellere Reaktionszeit gewährleisten. Wenn die Reaktionszeit für diese spezifischen Elemente entscheidend ist, sind alternative Stream-Prozessoren wie Apache Flink oder Apache Storm vielleicht besser geeignet. Wenn du aber nur an einer durchschnittlich schnellen Verarbeitung interessiert bist, z. B. bei der Überwachung eines Systems, ist Spark ein interessanter Vorschlag.

Durchsatzorientierte Verarbeitung

Alle Alles in allem zeichnet sich Spark bei der Stream-Verarbeitung vor allem durch die durchsatzorientierte Datenanalyse aus.

Wir können den Microbatch-Ansatz mit einem Zug vergleichen: Er kommt am Bahnhof an, wartet eine bestimmte Zeit auf Fahrgäste und befördert dann alle Fahrgäste, die zugestiegen sind, zu ihrem Ziel. Obwohl ein Fahrgast mit einem Auto oder einem Taxi für dieselbe Strecke vielleicht schneller von Tür zu Tür reisen kann, sorgt die Menge an Fahrgästen im Zug dafür, dass viel mehr Reisende an ihrem Ziel ankommen. Der Zug bietet einen höheren Durchsatz für dieselbe Strecke, allerdings um den Preis, dass einige Fahrgäste warten müssen, bis der Zug abfährt.

Die Kern-Engine von Spark ist für die verteilte Stapelverarbeitung optimiert. Ihre Anwendung in einem Streaming-Kontext stellt sicher, dass große Datenmengen pro Zeiteinheit verarbeitet werden können. Spark amortisiert den Overhead der verteilten Aufgabenplanung, indem es viele Elemente auf einmal verarbeitet und, wie wir bereits in diesem Kapitel gesehen haben, In-Memory-Techniken, Abfrageoptimierungen, Caching und sogar Codegenerierung einsetzt, um den Transformationsprozess eines Datensatzes zu beschleunigen.

Beim Einsatz von Spark in einer End-to-End-Anwendung ist es wichtig, dass die nachgelagerten Systeme, die die verarbeiteten Daten erhalten, auch in der Lage sind, die gesamte Ausgabe des Streaming-Prozesses zu verarbeiten. Andernfalls besteht die Gefahr, dass es zu Engpässen in der Anwendung kommt, die bei plötzlichen Lastspitzen zu kaskadenartigen Ausfällen führen können.

Die polyglotte API von Spark

Wir haben nun die wichtigsten Designgrundlagen von Apache Spark in Bezug auf die Stream-Verarbeitung skizziert, nämlich eine reichhaltige API und ein In-Memory-Verarbeitungsmodell, das im Rahmen des Modells einer Ausführungsmaschine definiert ist. Wir haben die spezifischen Streaming-Modi von Apache Spark untersucht und festgestellt, dass Spark aufgrund des vorherrschenden Microbatching eher für durchsatzorientierte Aufgaben geeignet ist, bei denen mehr Daten mehr Qualität ergeben. Wir wollen nun unsere Aufmerksamkeit auf einen weiteren Aspekt lenken, bei dem Spark glänzt: sein Programmier-Ökosystem.

Spark wurde zunächst als reines Scala-Projekt programmiert. Als das Interesse und die Akzeptanz zunahmen, wurde es notwendig, verschiedene Nutzerprofile mit unterschiedlichen Hintergründen und Programmiersprachenkenntnissen zu unterstützen. In der Welt der wissenschaftlichen Datenanalyse sind Python und R wohl die vorherrschenden Sprachen der Wahl, während im Unternehmensumfeld Java eine dominierende Stellung einnimmt.

Spark ist bei weitem nicht mehr nur eine Bibliothek für die Verteilung von Berechnungen, sondern ein polyglottes Framework, das der Nutzer mit Scala, Java, Python oder der Sprache R bedienen kann. Die Entwicklungssprache ist immer noch Scala, und hier liegen die wichtigsten Innovationen.

Vorsicht

Die Abdeckung der Java-API ist dank der ausgezeichneten Java-Kompatibilität der Scala-Sprache seit langem ziemlich synchron mit Scala. Und obwohl Python in Spark 1.3 und früheren Versionen in Bezug auf die Funktionalitäten hinterherhinkte, ist es jetzt größtenteils aufgeholt. Der jüngste Neuzugang ist R, bei dem die Vollständigkeit der Funktionen noch in Arbeit ist.

Diese vielseitige Schnittstelle hat dazu geführt, dass Programmierer mit unterschiedlichem Niveau und Hintergrund zu Spark strömen, um ihre eigenen Datenanalysen zu implementieren. Die erstaunliche und wachsende Vielfalt der Beiträge zum Open-Source-Projekt Spark zeugt von der Stärke von Spark als föderatives Framework.

Der Ansatz von Spark, die Datenverarbeitung seiner Nutzerinnen und Nutzer bestmöglich zu unterstützen, geht jedoch darüber hinaus, ihnen die Möglichkeit zu geben, ihre bevorzugte Programmiersprache zu verwenden.

Schnelle Umsetzung der Datenanalyse

Die Vorteile von Spark bei der Entwicklung einer Streaming-Data-Analytics-Pipeline liegen nicht nur in der übersichtlichen High-Level-API in Scala und den kompatiblen APIs in Java und Python, sondern auch in dem einfachen Modell von Spark, das eine praktische Abkürzung im Entwicklungsprozess darstellt.

Die Wiederverwendung von Komponenten mit Spark ist ein wertvoller Vorteil, ebenso wie der Zugang zum Java-Ökosystem von Bibliotheken für maschinelles Lernen und viele andere Bereiche. Mit Spark können Nutzer zum Beispiel problemlos die Stanford CoreNLP-Bibliothek nutzen und sich die mühsame Aufgabe ersparen, einen Tokenizer zu schreiben. Alles in allem kannst du so schnell einen Prototyp deiner Streaming Data Pipeline-Lösung erstellen und erhältst schnell genug erste Ergebnisse, um bei jedem Schritt der Pipeline-Entwicklung die richtigen Komponenten auszuwählen.

Schließlich profitierst du bei der Stream-Verarbeitung mit Spark von seinem Modell der Fehlertoleranz, das dir die Gewissheit gibt, dass fehlerhafte Maschinen die Streaming-Anwendung nicht in die Knie zwingen werden. Wenn du den automatischen Neustart fehlgeschlagener Spark-Aufträge genossen hast, wirst du diese Ausfallsicherheit beim Betrieb eines 24/7-Streaming-Betriebs doppelt zu schätzen wissen.

Zusammenfassend lässt sich sagen, dass Spark ein Framework ist, das zwar Kompromisse bei der Latenz eingeht, aber gleichzeitig den Aufbau einer agilen Datenanalyse-Pipeline optimiert: Schnelles Prototyping in einer reichhaltigen Umgebung und stabile Laufzeitleistung unter widrigen Bedingungen sind Probleme, die es erkennt und direkt angeht und den Nutzern erhebliche Vorteile bietet.

Um mehr über Spark zu erfahren

Dieses Buch ist auf Streaming ausgerichtet. Daher gehen wir schnell durch die Spark-zentrierten Konzepte, insbesondere zur Stapelverarbeitung. Die ausführlichsten Referenzen sind [Karau2015] und [Chambers2018].

Die offizielle Dokumentation im Spark-Programmierhandbuch ist eine weitere Pflichtlektüre.

Zusammenfassung

In diesem Kapitel hast du erfahren, was Spark ist und woher es kommt.

  • Du hast gesehen, wie Spark dieses Modell mit wichtigen Leistungsverbesserungen erweitert, insbesondere mit In-Memory-Computing, und wie es die API mit neuen Funktionen höherer Ordnung erweitert.

  • Wir haben uns auch angesehen, wie sich Spark in das moderne Ökosystem der Big-Data-Lösungen einfügt, einschließlich des kleineren Fußabdrucks, auf den es sich im Vergleich zu seinem älteren Bruder Hadoop konzentriert.

  • Wir konzentrierten uns auf die Streaming-APIs und insbesondere auf die Bedeutung ihres Microbatching-Ansatzes, für welche Anwendungen sie geeignet sind und für welche Anwendungen sie nicht geeignet sind.

  • Abschließend haben wir uns mit der Stream-Verarbeitung im Kontext von Spark befasst und gezeigt, wie der Aufbau einer flexiblen Pipeline zusammen mit einer zuverlässigen, fehlertoleranten Bereitstellung der beste Anwendungsfall ist.

Get Stream Processing mit Apache Spark 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.