2 - Trabajando Con RDDs Spark Curso BIT (CasiFin)
2 - Trabajando Con RDDs Spark Curso BIT (CasiFin)
1
Trabajando con RDDs
RDD: Resilient Distributed Dataset: es una simple, RESILIENTE e
INMUTABLE colección DISTRIBUIDA de objetos.
◦ Es RESILIENTE (tolerante a fallos): Podemos recuperar los datos en
memoria si se pierden.
◦ Es INMUTABLE: no podemos realizar modificaciones sobre un mismo
RDD. Si queremos modificarlo tendremos que crear uno nuevo.
◦ Es DISTRIBUIDO: cada RDD es dividido en múltiples particiones
automáticamente. El RDD puede ser ejecutado en diferentes nodos del
clúster.
◦ DATASET: Conjunto de datos. 2 tipos de fuentes: externas, datos en
memoria.
2
Trabajando con RDDs
Los usuarios pueden crear RDDs de dos maneras
◦ Transformando un RDD que ya existe
◦ Desde un objeto SparkContext distribuyendo una colección de objetos (ej: una
lista) en su driver
3
Trabajando con RDDs
El Spark Context es la manera que tenemos de comunicarnos
con el clúster
El método Parallelize convierte una Scala Collection local en un
RDD
4
Trabajando con RDDs
Transformaciones
◦ Son perezosas: Spark no procesa las transformaciones
sobre RDD's hasta que no se ejecuta una acción sobre
ellos.
◦ El RDD resultado no es inmediatamente computado
Acciones
◦ No son perezosas: Eager
◦ El resultado es inmediatamente computado
Esta es la forma que tiene Spark de reducir el tráfico de red. Una vez que Spark ve toda la cadena de
transformaciones, puede procesar solo los datos que necesita para el resultado de la acción.
Ejemplo: Solo ejecutará las operaciones necesarias para obtener el valor del primer elemento del RDD.
5
Trabajando con RDDs
Ejemplo
◦ Supongamos que tenemos este código
RDD [String]
RDD [Int]
6
Trabajando con RDDs
Ejemplo
◦ Supongamos que tenemos este código
RDD [String]
RDD [Int]
7
Trabajando con RDDs
Ejemplo
◦ Supongamos que tenemos este otro código
8
Trabajando con RDDs
Aunque pueda resultar sorprendente a primera
vista, trabajar con transformaciones y acciones
tiene mucho sentido al trabajar con Big Data
Imaginemos, por ejemplo, que queremos
cargar un gran dataset de URLs y
posteriormente contar las veces que una
determinada IP accede a una determinada
URL.
Si ejecutásemos la primera transformación
según se escribe el comando, perderíamos
mucho tiempo y espacio al almacenar todo el
dataset en memoria dado que solo queremos
unas determinadas IPs y URLs.
En su lugar, Spark interpreta la cadena total de
transformaciones y computa solamente
aquellos datos que necesita para obtener el
resultado
9
Trabajando con RDDs
Como hemos visto, los RDDs son
computados cada vez que se realiza una
acción.
10
Trabajando con RDDs: Transformaciones
Transformaciones
◦ Aplican Lazy Evaluation
◦ val inputRDD = sc.textFile("log.txt")
◦ val errorsRDD = inputRDD.filter(line => line.contains("error"))
◦ En este ejemplo, filter no cambia el contenido de inputRDD, simplemente crea
punteros a un nuevo RDD, de manera que puede volver a ser reutilizado.
◦ errorsRDD = inputRDD.filter(line => line.contains("error"))
◦ warningsRDD = inputRDD.filter(line => line.contains(“warning")))
◦ badLinesRDD = errorsRDD.union(warningsRDD)
◦ Esta forma de trabajar hace que, en caso de pérdida de datos, se pueda volver a procesar todo
de nuevo, de manera que no se pierda nada.
11
Trabajando con RDDs: Transformaciones
Transformaciones más usadas
map()
◦ que genera un nuevo RDD aplicando alguna función sobre cada línea del RDD
filter()
◦ Toma una función y la aplica a los elementos del RDD que cumplen el filtro. Básicamente hace
lo mismo que el “where” en SQL
12
Trabajando con RDDs: Transformaciones
Transformaciones más usadas
flatMap()
◦ A veces queremos obtener como salida varios elementos dado uno de entrada
◦ Como map(), la función que le pasamos se aplica a cada elemento del RDD
individualmente, pero en lugar de devolver un solo resultado compuesto por el
resultado de aplicar dicha función a cada elemento, se itera sobre cada elemento
inicial y se devuelve un valor por cada iteración
◦ Una forma sencilla de entenderlo es, teniendo como entrada una frase, devolver
una lista de palabras
13
Trabajando con RDDs
Ejercicio
Asumimos que tenemos un RDD[String] que contiene GBs de logs del año
pasado. Cada elemento del RDD es una línea de logs.
Asumimos que las fechas están en formato YYYY-MM-DD:HH:MM:SS y que los
errores tienen el prefijo “error”
Existe una función contains() que devuelve las tuplas que contienen la cadena
de caracteres que se pase como parámetro.
Existe una función count() que cuenta filas
Pregunta: cómo determinamos cuántos errores han ocurrido en Diciembre de
2016?
val logs_ano_pasado: RDD[String]:…
14
Trabajando con RDDs: Acciones
La acción más típica es
reduce() -- los tipos de entrada y salida son iguales
◦ Opera sobre dos elementos del RDD y devuelve un resultado
◦ El ejemplo más simple es la suma de elementos
◦ De este modo es sencillo realizar sumas, cuentas o agregaciones
◦ val sum = rdd.reduce((x, y) => x + y)
◦ Todos los elementos del RDD deben ser del mismo tipo
Otro ejemplo, operación foldLeft (el tipo de datos de entrada es de un tipo y la salida puede ser de
otro)
15
Trabajando con RDDs: Acciones
Acciones (2)
◦ Existe la función collect() para devolver el dataset completo, pero
recordemos que el dataset será copiado al driver (nodo maestro) y una
excepción será lanzada si es demasiado grande para caber en memoria, por
lo que solo lo usaremos para pequeños datasets
◦ Para casos en los que queramos usar collect() en datasets muy grandes,
podemos hacer que su resultado se almacene en algún sistema de
almacenamiento, en lugar de en el driver, como Amazon s3 o HDFS
◦ Para ello podemos usar funciones como saveAsSequenceFile()
◦ Recordad que cada vez que ejecutamos una Acción, se debe ejecutar la
secuencia completa de transformaciones sobre el RDD, por lo que
conviene tener en mente la opción de persistir datos intermedios de vez
en cuando.
16
Trabajando con RDDs: Acciones
Acciones más usadas
count(), que cuenta el número de elementos (filas) de un RDD
take(n), que devuelve un array de n elementos
collect(), que devuelve un array de todos los elementos
saveAsTextfile(file), que guarda el RDD a un fichero de texto
Fichero_entrada.txt
17
Trabajando con RDDs
Ejemplo para mostrar el valor del "lazy fashion" de las transformaciones
18
Trabajando con RDDs: foldLeft
*No todo es paralelizable y distribuible: dividir el total en piezas y trabajar sobre cada pieza
Pero, y si en lugar de una suma de enteros tenemos algo como esto?
A, B representa el tipo de datos de entrada
19
20
Trabajando con RDDs: Reduce
Solución: utilizar la función aggregate
21
Transformaciones típicas
distinct(), union(), intersection(), subtract(), cartesian()
22
Listado de transformaciones
RDD = {1, 2, 3, 3}
23
Listado de transformaciones
RDDs = {1, 2, 3} y {3, 4, 5}
24
Listado de acciones
RDD = {1, 2, 3, 3}
25
Listado de acciones
RDD = {1, 2, 3, 3}
26
Ejercicios
Ejercicio
- SPK2-Ejercicio: Comenzando con los RDDs (módulo 2)
27