Einführung in Apache Beam

1. Übersicht

In diesem Tutorial werden wir Apache Beam vorstellen und seine grundlegenden Konzepte untersuchen.

Zunächst werden der Anwendungsfall und die Vorteile der Verwendung von Apache Beam demonstriert und anschließend grundlegende Konzepte und Terminologien behandelt. Anschließend werden wir ein einfaches Beispiel durchgehen, das alle wichtigen Aspekte von Apache Beam veranschaulicht.

2. Was ist Apache Beam?

Apache Beam (Batch + strEAM) ist ein einheitliches Programmiermodell für Batch- und Streaming-Datenverarbeitungsjobs. Es enthält ein Software-Entwicklungskit zum Definieren und Erstellen von Datenverarbeitungs-Pipelines sowie von Läufern, um diese auszuführen.

Apache Beam wurde entwickelt, um eine tragbare Programmierschicht bereitzustellen. Tatsächlich übersetzen die Beam Pipeline Runners die Datenverarbeitungspipeline in die API, die mit dem Backend der Wahl des Benutzers kompatibel ist. Derzeit werden diese verteilten Verarbeitungs-Backends unterstützt:

  • Apache Apex
  • Apache Flink
  • Apache Gearpump (Inkubation)
  • Apache Samza
  • Apache Spark
  • Google Cloud-Datenfluss
  • Hazelcast Jet

3. Warum Apache Beam?

Apache Beam fusioniert die Stapel- und Streaming-Datenverarbeitung, während andere dies häufig über separate APIs tun. Folglich ist es sehr einfach, einen Streaming-Prozess in einen Batch-Prozess umzuwandeln und umgekehrt, wenn sich beispielsweise die Anforderungen ändern.

Apache Beam erhöht die Portabilität und Flexibilität. Wir konzentrieren uns eher auf unsere Logik als auf die zugrunde liegenden Details. Darüber hinaus können wir das Datenverarbeitungs-Backend jederzeit ändern.

Für Apache Beam stehen Java-, Python-, Go- und Scala-SDKs zur Verfügung. In der Tat kann jeder im Team es mit der Sprache seiner Wahl verwenden.

4. Grundlegende Konzepte

Mit Apache Beam können wir Workflow-Diagramme (Pipelines) erstellen und ausführen. Die Schlüsselkonzepte im Programmiermodell sind:

  • PCollection - stellt einen Datensatz dar, der ein fester Stapel oder ein Datenstrom sein kann
  • Ptransform - eine Datenverarbeitungsoperation , die eine oder mehrere nimmt PCollection s und Ausgänge null oder mehr PCollection s
  • Pipeline - stellt einen gerichteten azyklischen Graphen von PCollection und PTransform dar und kapselt daher den gesamten Datenverarbeitungsjob
  • PipelineRunner - führt eine Pipeline in einem angegebenen verteilten Verarbeitungs-Backend aus

Einfach ausgedrückt, ein PipelineRunner führt eine Pipeline aus, und eine Pipeline besteht aus PCollection und PTransform .

5. Beispiel für die Wortanzahl

Nachdem wir die grundlegenden Konzepte von Apache Beam kennengelernt haben, können wir eine Wortzählaufgabe entwerfen und testen.

5.1. Aufbau einer Beam-Pipeline

Das Entwerfen des Workflow-Diagramms ist der erste Schritt in jedem Apache Beam-Job. Definieren wir die Schritte einer Wortzählaufgabe:

  1. Lesen Sie den Text aus einer Quelle.
  2. Teilen Sie den Text in eine Liste von Wörtern.
  3. Alle Wörter in Kleinbuchstaben.
  4. Interpunktionen kürzen.
  5. Stoppwörter filtern.
  6. Zähle jedes einzelne Wort.

Um dies zu erreichen, müssen wir die obigen Schritte mithilfe von PCollection- und PTransform- Abstraktionen in eine einzelne Pipeline konvertieren .

5.2. Abhängigkeiten

Bevor wir unser Workflow-Diagramm implementieren können, sollten wir die Kernabhängigkeit von Apache Beam zu unserem Projekt hinzufügen:

 org.apache.beam beam-sdks-java-core ${beam.version} 

Beam Pipeline Runners verlassen sich auf ein verteiltes Verarbeitungs-Backend, um Aufgaben auszuführen. Fügen wir DirectRunner als Laufzeitabhängigkeit hinzu:

 org.apache.beam beam-runners-direct-java ${beam.version} runtime 

Im Gegensatz zu anderen Pipeline-Läufern benötigt DirectRunner kein zusätzliches Setup, was es für Anfänger zu einer guten Wahl macht.

5.3. Implementierung

Apache Beam verwendet das Map-Reduce-Programmierparadigma (wie Java Streams). In der Tat ist es eine gute Idee, ein grundlegendes Konzept von redu () , filter () , count () , map () und flatMap () zu haben, bevor wir fortfahren.

Das Erstellen einer Pipeline ist das erste, was wir tun:

PipelineOptions options = PipelineOptionsFactory.create(); Pipeline p = Pipeline.create(options);

Jetzt wenden wir unsere sechsstufige Wortzählaufgabe an:

PCollection
    
      wordCount = p .apply("(1) Read all lines", TextIO.read().from(inputFilePath)) .apply("(2) Flatmap to a list of words", FlatMapElements.into(TypeDescriptors.strings()) .via(line -> Arrays.asList(line.split("\\s")))) .apply("(3) Lowercase all", MapElements.into(TypeDescriptors.strings()) .via(word -> word.toLowerCase())) .apply("(4) Trim punctuations", MapElements.into(TypeDescriptors.strings()) .via(word -> trim(word))) .apply("(5) Filter stopwords", Filter.by(word -> !isStopWord(word))) .apply("(6) Count words", Count.perElement());
    

Das erste (optionale) Argument von apply () ist ein String , der nur zur besseren Lesbarkeit des Codes dient. Hier ist, was jeder apply () im obigen Code tut:

  1. Zuerst lesen wir eine Eingabetextdatei zeilenweise mit TextIO .
  2. Wir teilen jede Zeile durch Leerzeichen auf und ordnen sie einer Liste von Wörtern zu.
  3. Word count is case-insensitive, so we lowercase all words.
  4. Earlier, we split lines by whitespace, ending up with words like “word!” and “word?”, so we remove punctuations.
  5. Stopwords such as “is” and “by” are frequent in almost every English text, so we remove them.
  6. Finally, we count unique words using the built-in function Count.perElement().

As mentioned earlier, pipelines are processed on a distributed backend. It's not possible to iterate over a PCollection in-memory since it's distributed across multiple backends. Instead, we write the results to an external database or file.

First, we convert our PCollection to String. Then, we use TextIO to write the output:

wordCount.apply(MapElements.into(TypeDescriptors.strings()) .via(count -> count.getKey() + " --> " + count.getValue())) .apply(TextIO.write().to(outputFilePath));

Now that our Pipeline definition is complete, we can run and test it.

5.4. Running and Testing

So far, we've defined a Pipeline for the word count task. At this point, let's run the Pipeline:

p.run().waitUntilFinish();

On this line of code, Apache Beam will send our task to multiple DirectRunner instances. Consequently, several output files will be generated at the end. They'll contain things like:

... apache --> 3 beam --> 5 rocks --> 2 ...

Defining and running a distributed job in Apache Beam is as simple and expressive as this. For comparison, word count implementation is also available on Apache Spark, Apache Flink, and Hazelcast Jet.

6. Where Do We Go From Here?

Wir haben jedes Wort aus unserer Eingabedatei erfolgreich gezählt, aber wir haben noch keinen Bericht über die häufigsten Wörter. Das Sortieren einer PC-Sammlung ist sicherlich ein gutes Problem, das wir als nächsten Schritt lösen müssen.

Später erfahren Sie mehr über Fenster, Trigger, Metriken und komplexere Transformationen. Die Apache Beam-Dokumentation bietet detaillierte Informationen und Referenzmaterial.

7. Fazit

In diesem Tutorial haben wir gelernt, was Apache Beam ist und warum es Alternativen vorgezogen wird. Wir haben auch grundlegende Konzepte von Apache Beam anhand eines Beispiels für die Wortanzahl demonstriert.

Der Code für dieses Tutorial ist auf GitHub verfügbar.