Persistenz in Apache Spark verstehen

Lesezeit: 4 Minuten

In diesem Blog werden wir versuchen, das Konzept der Persistenz in Apache Spark in einem sehr Laien Begriff mit Szenario-basierten Beispielen zu verstehen.
Hinweis: Die Szenarien sind nur zum besseren Verständnis gedacht.

Spark-Architektur

Hinweis: Cache-Speicher kann zwischen Executoren gemeinsam genutzt werden.

Was bedeutet es, eine RDD beizubehalten / zwischenzuspeichern?

Spark RDD Persistence ist eine Optimierungstechnik, die das Ergebnis der RDD-Auswertung im Cache-Speicher speichert. Damit speichern wir das Zwischenergebnis, um es bei Bedarf weiter verwenden zu können. Es reduziert den Rechenaufwand.

Wenn wir eine RDD beibehalten, speichert jeder Knoten die Partitionen, die er berechnet, im Speicher und verwendet sie in anderen Aktionen für diese RDD (oder von ihr abgeleitete RDD). Dadurch können zukünftige Aktionen viel schneller ausgeführt werden (oft um mehr als das 10-fache). Caching ist ein Schlüsselwerkzeug für iterative Algorithmen und schnelle interaktive Nutzung.

Sie können eine RDD mit den Methoden persist() oder cache() als persistent markieren. Wenn es zum ersten Mal in einer Aktion berechnet wird, wird es im Cache-Speicher auf den Knoten gespeichert. Der Cache von Spark ist fehlertolerant – wenn eine Partition einer RDD verloren geht, wird sie automatisch mit den Transformationen neu berechnet, die sie ursprünglich erstellt haben.

Nehmen wir an, ich habe diese Transformation –

RDD3 => RDD2 => RDD1 => Text FileRDD4 => RDD3RDD5 => RDD3

RDD3 wird aus RDD2 und RDD2 aus RDD1 erstellt. Jedes Mal, wenn wir eine Transformation für RDD3 durchführen, müssen RDD2 und RDD1 immer wieder neu berechnet werden.

RDD4.collect()RDD5.collect()

Hier muss die gesamte Transformationskette zweimal berechnet werden.

Wir können dieses RDD3 jedoch im Cache-Speicher des Worker-Knotens beibehalten, sodass RDD2 und RDD1 bei jeder Verwendung nicht neu berechnet werden müssen.

RDD3.cache()RDD4.collect()//The first action which involves RDD3 will store it in cache memoryRDD5.collect()

Hier liest Spark zur Berechnung von RDD5 RDD3 aus dem Cache-Speicher und generiert das Ergebnis. Daher werden RDD2 und RDD1 für RDD5

nicht neu berechnet Hinweis: rdd.cache() ist dasselbe wie rdd.persist()

Persistenzstufen

Speicherort

– MEMORY_ONLY (Standard) – wie Cache
rdd.persist(StorageLevel.MEMORY_ONLY) oder rdd.persist()

– MEMORY_AND_DISK – Speichert Partitionen auf der Festplatte, die nicht in den Speicher passen (Dies wird auch als Verschütten bezeichnet)
rdd.persist(StorageLevel.MEMORY_AND_DISK )

– DISK_ONLY – Speichert alle Partitionen auf der Festplatte
rdd.persist(StorageLevel.DISK_ONLY )

– MEMORY_ONLY (Standard) – Dies ist die einfachste und am meisten empfohlene Verwendung. Es speichert alle Partitionen von RDD im Cache-Speicher.

– DISK_ONLY – Angenommen, ich habe eine RDD (mit dem Namen RDD1) und die Berechnung dieser RDD ist sehr kompliziert (zeitaufwändig, erstellt nach Anwendung eines ML-Algorithmus) und die RDD ist riesig und der verfügbare Cache-Speicher im Worker-Knoten ist geringer, sodass wir die RDD nicht im Cache-Speicher speichern können. In diesem Fall können wir die RDD auf der Festplatte speichern.

Sie fragen sich vielleicht, wozu das Speichern auf der Festplatte dient?

Wenn wir die RDD auf der Festplatte speichern, erfolgt definitiv eine E / A, was zeitaufwändig ist. Wir müssen jedoch sicherstellen, dass die E / A lange dauert oder die Neuberechnung der RDD länger dauert. Wenn wir nun herausfinden können, dass die E / A weniger Zeit in Anspruch nimmt als die Neuberechnung der RDD, ist es in diesem Fall besser, die RDD auf der Festplatte zu speichern.

Wenn also RDD1 das nächste Mal in der nachfolgenden Transformation benötigt wird, führt Spark eine E / A-Operation aus und bringt sie in den Speicher des Executors.

RDD1.persist(StorageLevel.DISK_ONLY)

– MEMORY_AND_DISK – Angenommen, ich habe 3 RDDs (keine werden zwischengespeichert) im Speicher des Executors und es ist kein Speicher mehr verfügbar. Inzwischen kommt eine andere RDD (sagen wir RDD4) herein. Spark entfernt also die zuletzt verwendete (LRU) RDD aus dem Speicher des Executors und schafft Platz für die neue RDD (in diesem Fall RDD4).

Nehmen wir nun an, dass 3 RDDs im Speicher zwischengespeichert sind und wenn RDD4 eintrifft, wird LRU keine RDD aus dem Cache-Speicher des Worker-Knotens entfernen. Und es kann OOM-Probleme geben.

Wenn wir jedoch die Persistenzstufe MEMORY_AND_DISK mit RDD4 verwenden, wird RDD4 auf der Festplatte gespeichert, wenn nicht genügend Speicherplatz im Cache-Speicher vorhanden ist.

RDD4.persist(StorageLevel.MEMORY_AND_DISK)

Wenn eine große RDD im Speicher zwischengespeichert wird und nicht genügend Cache-Speicher vorhanden ist, werden die verbleibenden Partitionen, die nicht in den Cache-Speicher passen, auf die Festplatte verschüttet, wenn wir MEMORY_AND_DISK verwenden.

Auch hier ist die Herausforderung I / O-Operationen.

Hinweis: Die auf der Festplatte gespeicherten Daten werden am Speicherort tmp gespeichert.

Speicherformat

Serialisierung – Wir können die im Cache-Speicher gespeicherten Daten serialisieren.

MEMORY_ONLY_SER und MEMORY_AND_DISK_SER

Das Beibehalten der RDD in einer serialisierten (binären) Form hilft, die Größe der RDD zu reduzieren, wodurch Platz für mehr RDD im Cache-Speicher bleibt. Diese beiden Speicherformate sind also platzsparend.

Das Problem dabei ist jedoch, dass sie weniger zeiteffizient sind, da wir die Zeitkosten für die Deserialisierung der Daten tragen müssen.

Es ist also die Wahl des Entwicklers, ob die Leistung oder der Speicher wichtig sind. Auf jeden Fall wären die Auswirkungen auf die Leistung nicht groß, aber es wäre eine Minute.

Partitionsreplikation

Speichert die Partition auf zwei Knoten.

DISK_ONLY_2
MEMORY_AND_DISK_2
MEMORY_ONLY_2
MEMORY_AND_DISK_SER_2
MEMORY_ONLY_SER_2

Diese Optionen speichern eine replizierte Kopie der RDD auch im Cache-Speicher eines anderen Worker-Knotens.

Replizierte Daten auf der Festplatte werden verwendet, um die Partition neu zu erstellen, z. es hilft, die RDD neu zu berechnen, wenn der andere Worker-Knoten ausfällt.

Aufhebung der Persistenz der RDD

– Um die Persistenz zu beenden und aus dem Speicher oder der Festplatte zu entfernen
– Um die Persistenzstufe einer RDD zu ändern
rdd.unpersist()

So können wir mit unserem Cache-Speicher in Apache Spark arbeiten.

Das ist alles aus diesem Blog, hoffe es hat dir gefallen und es hat dir geholfen!! Bleiben Sie in Verbindung für weitere zukünftige Blogs. Vielen Dank!!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.