Comprendere la persistenza in Apache Spark

Reading Time: 4 minutes

In questo blog, cercheremo di comprendere il concetto di persistenza in Apache Spark in un termine molto laico con esempi basati su scenari.
Nota: Gli scenari sono pensati solo per la tua facile comprensione.

Architettura Spark

Nota: la memoria cache può essere condivisa tra gli esecutori.

Cosa significa persistere / memorizzare nella cache un RDD?

Spark RDD persistence è una tecnica di ottimizzazione che salva il risultato della valutazione RDD nella memoria cache. Usando questo salviamo il risultato intermedio in modo che possiamo usarlo ulteriormente se necessario. Riduce il sovraccarico di calcolo.

Quando persistiamo un RDD, ogni nodo memorizza le partizioni di esso che calcola in memoria e le riutilizza in altre azioni su quell’RDD (o RDD derivato da esso). Ciò consente alle azioni future di essere molto più veloci (spesso di oltre 10 volte). Il caching è uno strumento chiave per algoritmi iterativi e un uso interattivo veloce.

È possibile contrassegnare un RDD da persistere utilizzando i metodi persist() o cache() su di esso. La prima volta che viene calcolato in un’azione, verrà mantenuto nella memoria cache sui nodi. La cache di Spark è fault-tolerant: se una partizione di un RDD viene persa, verrà automaticamente ricalcolata utilizzando le trasformazioni che l’hanno originariamente creata.

Diciamo che ho questa trasformazione–

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

RDD3 viene creato da RDD2 e RDD2 viene creato da RDD1. Ogni volta che eseguiamo una trasformazione su RDD3, RDD2 e RDD1 devono essere ricalcolati ancora e ancora.

RDD4.collect()RDD5.collect()

Qui, l’intera catena di trasformazione deve essere calcolata due volte.

Ma possiamo mantenere questo RDD3 nella memoria cache del nodo Worker in modo che ogni volta che lo usiamo, RDD2 e RDD1 non debbano essere ricalcolati.

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

Qui, per calcolare RDD5 Spark leggerà RDD3 dalla memoria cache e genererà il risultato. Quindi RDD2 e RDD1 non saranno ricalcolati per RDD5

Nota: rdd.cache () è uguale a rdd.persist()

Livelli di persistenza

Posizione di archiviazione

– MEMORY_ONLY (default) – come cache
rdd.persist (StorageLevel.MEMORY_ONLY) o rdd.persist()

– MEMORY_AND_DISK – Memorizza le partizioni su disco che non si adattano alla memoria (questo è anche chiamato Spilling)
rdd.persist (StorageLevel.MEMORY_AND_DISK )

– DISK_ONLY-Memorizza tutte le partizioni sul disco
rdd.persist (StorageLevel.DISK_ONLY )

– DISK_ONLY – Diciamo che ho un RDD (chiamato RDD1) e il calcolo di quell’RDD è molto complicato (richiede molto tempo, creato dopo aver applicato un algoritmo ML) e l’RDD è di dimensioni enormi e la memoria cache disponibile nel nodo Worker è inferiore, quindi non possiamo salvare l’RDD nella memoria cache. In questo caso, possiamo salvare l’RDD su DISCO.

Potresti chiederti qual è il punto di memorizzare nel disco?

Sicuramente, se memorizziamo l’RDD nel disco, si verificherà l’I / O, che richiede molto tempo. Ma dobbiamo assicurarci che l’I / O richieda molto tempo o che il ricalcolo dell’RDD richieda più tempo. Ora, se possiamo scoprire che l’I/O richiede meno tempo, allora il ricalcolo dell’RDD, allora in quel caso, è meglio memorizzare l’RDD su Disco.

Quindi, ogni volta che RDD1 è richiesto la prossima volta nella trasformazione successiva, Spark eseguirà un’operazione di I/O e la porterà nella memoria dell’Esecutore.

RDD1.persist (StorageLevel.DISK_ONLY)

Ora, supponiamo che 3 RDD siano memorizzati nella cache e quando arriva RDD4 LRU non estrarrà alcun RDD dalla memoria cache del Nodo Worker. E ci possono essere problemi OOM.

Ma se usiamo il livello di persistenza MEMORY_AND_DISK con RDD4, RDD4 verrà memorizzato nel Disco, se non trova abbastanza spazio nella memoria cache.

RDD4.persist (StorageLevel.MEMORY_AND_DISK)

Inoltre, se un enorme RDD è memorizzato nella cache e non c’è abbastanza memoria cache, le partizioni rimanenti che non sono in grado di adattarsi alla memoria cache vengono riversate su Disco se usiamo MEMORY_AND_DISK.

Ancora una volta la sfida qui sono le operazioni di I/O.

Nota: I dati persistiti nel disco sono memorizzati nella posizione tmp.

Formato di memoria

Serializzazione-Possiamo scegliere di serializzare i dati memorizzati nella memoria cache.

MEMORY_ONLY_SER e MEMORY_AND_DISK_SER

La persistenza dell’RDD in una forma serializzata (binaria) aiuta a ridurre le dimensioni dell’RDD, rendendo così lo spazio per la persistenza di più RDD nella memoria cache. Quindi questi due formati di memoria sono efficienti nello spazio.

Ma il problema con questo è che sono meno efficienti in termini di tempo perché dobbiamo sostenere il costo del tempo necessario per deserializzare i dati.

Quindi è una scelta dello sviluppatore se le prestazioni contano o le questioni di archiviazione. Sicuramente, l’impatto sulle prestazioni non sarebbe molto,ma sarebbe un minuto.

Replica partizione

Memorizza la partizione su due nodi.

DISK_ONLY_2
MEMORY_AND_DISK_2
MEMORY_ONLY_2
MEMORY_AND_DISK_SER_2
MEMORY_ONLY_SER_2

Queste opzioni memorizzano una copia replicata dell’RDD anche nella memoria cache di qualche altro Nodo di lavoro.

I dati replicati sul disco verranno utilizzati per ricreare la partizione, ad esempio aiuta a ricalcolare l’RDD se l’altro nodo worker va giù.

Unpersisting RDD

– Per interrompere la persistenza e rimuovere dalla memoria o dal disco
– Per modificare il livello di persistenza di un RDD
rdd.unpersist ()

Quindi, questo come possiamo lavorare con la nostra memoria cache in Apache Spark.

Questo è tutto da questo blog, spero che ti sia piaciuto e ti ha aiutato!! Rimani connesso per ulteriori blog futuri. Grazie!!

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.