Vous êtes sur la page 1sur 33

Curso Spark

01 Núcleo de Conceptos
Resilient Distributed Dataset

• Resilient Distributed Dataset (RDD) es una colección de objetos distribuida


de forma inmutable.
• Cada RDD es dividido en múltiples particiones , las cuales serán procesadas
en diferentes nodos dentro del cluster.
• Se puede crear RDDs de dos maneras, cargando un archivo de datos externo
o mediante la distribución de una colección de objetos (ie. list o set) en el
programa controlador.
Resilient Distributed Dataset

• ¿Cómo crearlo?
• Colección de objetos existente
Python
lineas = sc.parellelize([“pandas”, “ositos”])
SCALA
lineas = sc.parellelize(List(“pandas”, “ositos”))
Resilient Distributed Dataset

• Archivo externo
Python
lineas = sc.parellelize(“/path/to/README.md”)
SCALA
lineas = sc.parellelize(“/path/to/README.md”)
Operaciones con RDD

• Se pueden realizar dos tipos de operaciones en SPARK:


• Transformaciones
• Acciones.
• Las transformaciones son operaciones con RDD que dan como resultado un
nuevo RDD.
• Acciones son operaciones que devuelven resultados.
Operaciones con RDD

• Transformaciones
• Dan como resultado un nuevo RDD.
• Son ejecutados de forma lazy, es decir, son ejecutadas sólo cuando son
utilizadas en una acción.
• Muchas transformaciones son element wise, esto es, trabajan sobre un
elemento a la vez.
Operaciones con RDD
• Transformaciones
Ejemplos:
Python
inputRDD = sc.textFile(“log.txt”)
errorsRDD = inputRDD.filter(lambda x: “error” in x)
warningsRDD = inputRDD.filter(lambda x: “error” in x)
badlinesRDD = errorRDD.union(warningsRDD)

SCALA
inputRDD = sc.textFile(“log.txt”)
errorsRDD = inputRDD.filter(line => line.contains(“error”))
Operaciones con RDD

• Acciones
• Son operaciones que dan como resultado un valor final hacia el programa
controlador o generan la instrucción de escritura al sistema externo de
almacenamiento.
• Las acciones forzan la evaluación de las transformaciones requeridas por el
RDD.
Operaciones con RDD
• Acciones
Ejemplo:
Python
print "Input had " + badLinesRDD.count() + " concerning lines"
print "Here are 10 examples:"
for line in badLinesRDD.take(10):
print line
SCALA
println("Input had " + badLinesRDD.count() + " concerning lines")
println("Here are 10 examples:")
badLinesRDD.take(10).foreach(println)
Operaciones con RDD

• Evaluación Lazy
• SPARK no ejecuta las transformaciones hasta que aparece una acción.
• Al llamar una transformación sobre un RDD la operación no es ejecutada de
forma inmediata. Spark sólo registra los metadatos para indicar la operación
solicitada.
• La ventaja de utilizar la evaluación lazy es agrupar operaciones.
• En SPARK no hay beneficio alguno de crear un mapeo complejo en lugar de
encadenar muchas operaciones simples.
Operaciones con RDD

• Pasar las funciones a SPARK


• Python
• Hay tres formas de pasar funciones en Python:
• Expresiones lambda
• Funciones globales
• Funciones locales
Operaciones con RDD
• Funciones globales y locales.
• Mediante el comando def se pueden definir funciones globales y locales.
• Expresiones lambda.
• Python permite la creación de funciones anónimas (funciones que no están
sujetas a un nombre) al momento de ejecutarse, utilizando una construcción
llamada “lambda”.
• Las expresiones lambda se utilizan para funciones que sólo van a ser
utilizadas una vez.
Operaciones con RDD

• Filtrado utilizando funciones lambda o funciones globales

word = rdd.filter(lambda s: "error" in s)

def containsError(s):
return "error" in s
word = rdd.filter(containsError)
Operaciones con RDD

• En SCALA se puede pasar funciones a través de los siguientes tres métodos:


• Inline
• Referencias a métodos
• Funciones estáticas.
Transformaciones
• Las dos transformaciones más comunes son:
• map
• filter

InputRDD
{1,2,3,4}

map x => x*x filter x => x != 1

Mapped RDD Filtered RDD


{1,4,9,16} {2,3,4}
Transformaciones

• Python Valores al cuadrado en un RDD


nums = sc.parallelize([1, 2, 3, 4])
squared = nums.map(lambda x: x * x).collect()
for num in squared:
print "%i " % (num)
• Scala Valores al cuadrado en un RDD
val input = sc.parallelize(List(1, 2, 3, 4))
val result = input.map(x => x * x)
println(result.collect().mkString(","))
Transformaciones
• flatmap
• Produce elementos múltiples a partir de cada elemento introducido.
• El ejemplo más común, llevar un párrafo a palabras.
flatMap() en Python, separando líneas en múltiples palabras
lines = sc.parallelize([“hola mundo ", "hi"])
words = lines.flatMap(lambda line: line.split(" "))
words.first() # resulta en "hola"

flatMap() en Scala, separando líneas en múltiples palabras


val lines = sc.parallelize(List(“hola mundo", "hi"))
val words = lines.flatMap(line => line.split(" "))
words.first() // resulta "hola"
Transformaciones
• Diferencia entre map y flatmap
Mapped RDD
{[“hola”, “México” ], [”hola”, “DF” ],
rdd1.map(tokenize)
[”hola”, “comunidad”, “global” ]}

RDD1
{“hola México”, ”hola DF”,
”hola comunidad global”}

Mapped RDD
rdd1.flatMap(tokenize) {[“hola” , ” México” , ”hola” , “DF” , ”hola”
, “comunidad”, “global”] }
Transformaciones

• Operaciones Pseudo Conjunto (Pseudo Set Operations).


RDD1 .distinct()
RDD1 {beisból, futból, maratón, tenis}
{beisból, beisból, futból,
maratón, tenis} RDD1 .union(RDD2)
{beisból, beisból, beisból, futból, futból,
maratón, tenis, basquetból}

RDD2 RDD1 .intersection(RDD2)


{beisból, futból, basquetból} {beisból, futból}

RDD1 .subtract(RDD2)
{maratón, tenis}
Transformaciones

• Operaciones Pseudo Conjunto (Pseudo Set Operations).

RDD1
{uno, dos, tres}
RDD1 .cartesian(RDD2)
{(uno,beisból), (uno, futból), (uno, basquetból),
RDD1.cartesian(RDD2)
(uno,beisból), (dos, futból), (dos, basquetból),
(tres,beisból), (tres, futból), (tres, basquetból)}
RDD2
{beisból, futból, basquetból}
Acciones
• El tipo de acción más común es reduce.
Ejemplo
reduce() in Python
sum = rdd.reduce(lambda x, y: x + y)

reduce() in Scala
val sum = rdd.reduce((x, y) => x + y)

• fold realiza la misma acción que reduce pero permite incorporar un valor inicial igual a 0, lo
cual es muy útil para listas vacías.
• Tanto fold como reduce requieren que el resultado sea del mismo tipo que los elementos del
RDD sobre los que se ejecuta la acción.
Acciones
• La función aggregate nos libera de la restricción de que el resultado sea del mismo tipo que el RDD
sobre el que estamos trabajando.
• aggregate() en Python
sumCount = nums.aggregate((0, 0),
(lambda acc, value: (acc[0] + value, acc[1] + 1),
(lambda acc1, acc2: (acc1[0] + acc2[0], acc1[1] + acc2[1]))))
return sumCount[0] / float(sumCount[1])

• aggregate() en Scala
val result = input.aggregate((0, 0))(
(acc, value) => (acc._1 + value, acc._2 + 1),
(acc1, acc2) => (acc1._1 + acc2._1, acc1._2 + acc2._2))
val avg = result._1 / result._2.toDouble
Acciones

• collect – envía todos los registros a nuestro manejador.


• take(n) – envía n elementos del RDD. El orden no es el esperado.
• takeOrdered(num)(ordering) – retorna un número de elementos basado en
el orden provisto.
• top() – si los datos están ordenados un una forma determinada, esta
instrucción permite extraer los elemento en la cima del RDD.
• takeSample(withReplacement, num, seed) – Esta función nos permite
tomar una muestra con o sin reemplazo.
Acciones

• count() – nos calcula el número de elementos.


• countByValue – calcula un mapa con un conteo de cada valor único del RDD.
• foreach – Permite ejecutar acciones en cada uno de los elementos en el
RDD, pero no devuelve resultado alguno al manejador.
Conversión entre RDD

• Algunas funciones sólo están disponibles sobre determinadas formas de


RDD.
• En SCALA, estos métodos no están definidos sobre la clase estándar de
RDD, para acceder a ellos nos debemos asegurar de que estamos tratando
con la clase especializada correcta.
Conversión entre RDD

• En SCALA la conversión a RDD con funciones espaciales es manejada


automáticamente utilizando conversiones implícitas.
• Se debe agregar al programa import org.apache.spark.SparkContext._ para
que los conversiones funcionen.
• Estos implícitos convierten un RDD varias clases de wrapper, tales como
DoubleRDDFunctions (para datos numéricos) y PairRDDFunctions (para
pares key/value) para poder utilizar funciones tales como mean() y
variance().
Conversión entre RDD

• El API de Python está estructurado de manera distinta a SCALA. En Python


todas las funciones son implementadas enbase a la clase del RDD pero
fallarán en la ejecución si el tipo de datos en el RDD es incorrecto.
Persistencia (Caching)

• Los RDD de SPARK son evaluados de forma lazy.


• En algunos casos deseamos hacer operaciones sobre un mismo RDD en
múltiples ocasiones.
• Si las operaciones se hacen por separado, SPARK las ejecutará cada vez que
se invoque la acción sobre el RDD.
• Esto puede ser muy costoso para algoritmos iterativos.
Persistencia (Caching)

• Para evitar el cómputo sobre un RDD en múltiples ocasiones, se le solicita a


SPARK un persist de los datos.
• Cuando se le solicita a SPARK un persist del RDD, los nodos que tienen el
RDD almacenan las particiones.
• Si un nodo que debe persistir los datos falla, SPARK recalculará las
particiones perdidas cuando sea necesario.
• También podemos replicar los datos en múltiples nodos si deseamos
administrar la falla de nodos sin hacer más lento el servicio.
Persistencia (Caching)

• Spark tiene muchos niveles de persistencia para elegir dependiendo de


nuestros objetivos.
• En la siguiente tabla se muestran los nivles de persistencia de
org.apache.spark.StorageLevel y pyspark.StorageLevel.
• Si se desea se puede replicar los datos en dos máquinas al agregar _2 al final
del nivel de almacenamiento.
Persistencia (Caching)
Espacio Tiempo En
Nivel utilizado CPU memoria En disco Comentarios
MEMORY_ONLY Alto Bajo Si No
MEMORY_ONLY_SER Bajo Alto Si No
Se vierte en disco si son demasiados datos
MEMORY_AND_DISK Alto Medio Algo Algo para ser almacenados en memoria
Se vierte en disco si son demasiados datos
para ser almacenados en memoria. Guarda
MEMORY_AND_DISK_SER Bajo Alto Algo Algo una representación serializada en memoria.
DISK_ONLY Bajo Alto No Si
Persistencia (Caching)

• Ejemplo de persist con SCALA


val result = input.map(x => x * x)
result.persist(StorageLevel.DISK_ONLY)
println(result.count())
println(result.collect().mkString(","))
Bibliografía

• Holden Karau, Andy Konwinski, Patrick Wendell, y Matei Zaharia.


“Learning SPARK” OREILLY 2015.
• Core Spark functionality,
http://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.
package

Vous aimerez peut-être aussi