Entendiendo la persistencia en Apache Spark

Tiempo de lectura: 4 minutos

En este blog, trataremos de entender el concepto de Persistencia en Apache Spark en un término muy sencillo con ejemplos basados en escenarios.
Nota: Los escenarios son solo para su fácil comprensión.

Arquitectura Spark

Nota: La memoria caché se puede compartir entre ejecutores.

¿Qué significa persistir/almacenar en caché un RDD?

La persistencia de RDD de Spark es una técnica de optimización que guarda el resultado de la evaluación de RDD en la memoria caché. Usando esto guardamos el resultado intermedio para que podamos usarlo más si es necesario. Reduce la sobrecarga de cómputo.

Cuando persistimos en un RDD, cada nodo almacena las particiones del mismo que calcula en memoria y las reutiliza en otras acciones sobre ese RDD (o RDD derivado de él). Esto permite que las acciones futuras sean mucho más rápidas (a menudo en más de 10 veces). El almacenamiento en caché es una herramienta clave para algoritmos iterativos y un uso interactivo rápido.

Puede marcar un RDD para que se conserve utilizando los métodos persist() o cache() en él. La primera vez que se calcula en una acción, se guardará en la memoria caché de los nodos. La caché de Spark es tolerante a fallos: si se pierde alguna partición de un RDD, se volverá a calcular automáticamente utilizando las transformaciones que la crearon originalmente.

Digamos que tengo esta transformación–

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

RDD3 se crea a partir de RDD2 y RDD2 se crea a partir de RDD1. Cada vez que hacemos una transformación en RDD3, entonces RDD2 y RDD1 necesitan ser recalculados una y otra vez.

RDD4.collect()RDD5.collect()

Aquí, toda la cadena de transformación debe calcularse dos veces.

Pero podemos persistir este RDD3 en la memoria caché del nodo de trabajo para que cada vez que lo utilicemos, RDD2 y RDD1 no necesiten ser re-calculados.

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

Aquí, para calcular RDD5, Spark leerá RDD3 de la memoria caché y generará el resultado. Por lo tanto, RDD2 y RDD1 no se volverán a calcular para RDD5

Nota: rdd.cache() es lo mismo que rdd.persist()

Niveles de persistencia

Ubicación de almacenamiento

– MEMORY_ONLY (predeterminado) – lo mismo que la caché
rdd.persist (StorageLevel.MEMORY_ONLY) o rdd.persist ()

– MEMORY_AND_DISK – Almacena particiones en el disco que no caben en la memoria (Esto también se llama derramamiento)
rdd.persist (StorageLevel.MEMORY_AND_DISK )

– DISK_ONLY-Almacena todas las particiones en el disco
rdd.persist (StorageLevel.DISK_ONLY )

– DISK_ONLY-Digamos que tengo un RDD (llamado RDD1) y el cálculo de ese RDD es muy complicado (consume mucho tiempo, creado después de aplicar un algoritmo ML) y el RDD es enorme en tamaño y la memoria caché disponible en el nodo de trabajo es menor, por lo que no podemos guardar el RDD en la memoria caché. En este caso, podemos guardar el RDD en el DISCO.

Puede preguntarse cuál es el punto de almacenamiento en disco?

Definitivamente, si almacenamos el RDD en el disco, se producirá E/S, lo que consume mucho tiempo. Pero necesitamos asegurarnos de que si la E/S toma mucho tiempo o el re-cálculo del RDD toma más tiempo. Ahora, si podemos descubrir que la E/S está tomando menos tiempo, entonces el re-cálculo del RDD, entonces en ese caso, es mejor almacenar el RDD en el disco.

Por lo tanto, siempre que se requiera RDD1 la próxima vez en la transformación posterior, Spark realizará una operación de E/S y la llevará a la memoria del Ejecutor.

RDD1.persist (StorageLevel.DISK_ONLY)

Ahora, supongamos que 3 RDD se almacenan en caché en la memoria y cuando llega RDD4, LRU no eliminará ningún RDD de la memoria caché del nodo de trabajo. Y puede haber problemas de OOM.

Pero si usamos el nivel de persistencia MEMORY_AND_DISK con RDD4, RDD4 se almacenará en el disco, si no encuentra suficiente espacio en la memoria caché.

RDD4.persist (StorageLevel.MEMORY_AND_DISK)

Además, si un RDD enorme se almacena en caché en la memoria y no hay suficiente memoria caché, las particiones restantes que no pueden caber en la memoria caché se derraman en el disco si usamos MEMORY_AND_DISK.

De nuevo, el desafío aquí son las operaciones de E/S.

Nota: Los datos conservados en el disco se almacenan en la ubicación tmp.

Formato de memoria

Serialización: Podemos elegir serializar los datos almacenados en la memoria caché.

MEMORY_ONLY_SER y MEMORY_AND_DISK_SER

Persistir el RDD en una forma serializada (binaria) ayuda a reducir el tamaño del RDD, haciendo así espacio para que más RDD se persistan en la memoria caché. Así que estos dos formatos de memoria son eficientes en espacio.

Pero el problema con esto es que son menos eficientes en el tiempo porque necesitamos incurrir en el costo de tiempo involucrado en la deserialización de los datos.

Por lo tanto, es la elección de un desarrollador si el rendimiento importa o el almacenamiento importa. Definitivamente, el impacto en el desempeño no sería mucho, pero sería un minuto.

La replicación de particiones

Almacena la partición en dos nodos.

DISK_ONLY_2
MEMORY_AND_DISK_2
MEMORY_ONLY_2
MEMORY_AND_DISK_SER_2
MEMORY_ONLY_SER_2

Estas opciones también almacenan una copia replicada del RDD en la memoria caché de algún otro nodo de trabajo.

Los datos replicados en el disco se utilizarán para recrear la partición, p. ej. ayuda a volver a calcular el RDD si el otro nodo de trabajo se cae.

Eliminar el RDD

– Para detener la persistencia y eliminarla de la memoria o del disco
– Para cambiar el nivel de persistencia de un RDD
rdd.unpersist ()

Así es como podemos trabajar con nuestra memoria caché en Apache Spark.

Todo esto es de este blog, ¡espero que lo hayas disfrutado y te haya ayudado!! Manténgase conectado para más blogs futuros. ¡Gracias!!

Deja una respuesta

Tu dirección de correo electrónico no será publicada.