En este módulo, profundizaremos en cómo Apache Spark maneja los trabajos (jobs) y las tareas (tasks). Comprender cómo Spark ejecuta y organiza el procesamiento de datos es crucial para optimizar el rendimiento y solucionar problemas en aplicaciones Spark.
- Conceptos Clave
1.1. Job (Trabajo)
Un trabajo en Spark es una unidad de trabajo que se ejecuta como resultado de una acción (como collect()
, save()
, count()
, etc.) en un RDD o DataFrame. Cada trabajo se divide en etapas (stages) y tareas (tasks).
1.2. Stage (Etapa)
Un trabajo se divide en una o más etapas. Cada etapa representa un conjunto de tareas que pueden ejecutarse en paralelo. Las etapas se determinan por las dependencias de ancho estrecho (narrow dependencies) y ancho amplio (wide dependencies).
1.3. Task (Tarea)
Una tarea es la unidad más pequeña de trabajo en Spark. Cada tarea se ejecuta en un solo fragmento de datos (partition) y se asigna a un ejecutor (executor).
- Ejecución de un Trabajo en Spark
2.1. Planificación de un Trabajo
Cuando se ejecuta una acción en un RDD o DataFrame, Spark crea un plan de ejecución lógico. Este plan se convierte en un plan físico que se divide en etapas y tareas.
2.2. Dependencias
- Narrow Dependencies (Dependencias Estrechas): Cada partición de un RDD depende de una partición de su RDD padre. Ejemplo:
map()
,filter()
. - Wide Dependencies (Dependencias Amplias): Cada partición de un RDD depende de múltiples particiones de su RDD padre. Ejemplo:
groupByKey()
,reduceByKey()
.
2.3. DAG (Directed Acyclic Graph)
Spark representa el plan de ejecución como un DAG. Cada nodo en el DAG representa un RDD y cada borde representa una transformación.
- Ejemplo Práctico
Veamos un ejemplo práctico para entender cómo Spark maneja los trabajos.
from pyspark.sql import SparkSession # Crear una sesión de Spark spark = SparkSession.builder.appName("EntendiendoTrabajosSpark").getOrCreate() # Crear un DataFrame de ejemplo data = [("Alice", 34), ("Bob", 45), ("Cathy", 29)] columns = ["Nombre", "Edad"] df = spark.createDataFrame(data, columns) # Realizar una transformación y una acción df_filtered = df.filter(df["Edad"] > 30) count = df_filtered.count() print(f"El número de personas mayores de 30 años es: {count}") # Detener la sesión de Spark spark.stop()
Explicación del Código
- Crear una sesión de Spark: Inicializamos una sesión de Spark.
- Crear un DataFrame: Creamos un DataFrame con datos de ejemplo.
- Transformación: Aplicamos un filtro para seleccionar personas mayores de 30 años.
- Acción: Contamos el número de filas que cumplen con el filtro.
- Detener la sesión de Spark: Cerramos la sesión de Spark.
Análisis del Trabajo
- Transformación (
filter
): Esta operación crea un nuevo DataFrame pero no ejecuta ninguna computación hasta que se llama a una acción. - Acción (
count
): Esta operación desencadena la ejecución del trabajo. Spark crea un DAG, lo divide en etapas y ejecuta las tareas correspondientes.
- Ejercicio Práctico
Ejercicio
Crea un DataFrame con datos de ventas de productos. Filtra los productos con ventas mayores a 100 unidades y calcula el total de ventas de estos productos.
# Crear una sesión de Spark spark = SparkSession.builder.appName("EjercicioTrabajosSpark").getOrCreate() # Crear un DataFrame de ejemplo data = [("ProductoA", 150), ("ProductoB", 80), ("ProductoC", 200)] columns = ["Producto", "Ventas"] df = spark.createDataFrame(data, columns) # Realizar una transformación y una acción df_filtered = df.filter(df["Ventas"] > 100) total_ventas = df_filtered.groupBy().sum("Ventas").collect()[0][0] print(f"El total de ventas de productos con más de 100 unidades es: {total_ventas}") # Detener la sesión de Spark spark.stop()
Solución
- Crear una sesión de Spark: Inicializamos una sesión de Spark.
- Crear un DataFrame: Creamos un DataFrame con datos de ventas de productos.
- Transformación (
filter
): Filtramos los productos con ventas mayores a 100 unidades. - Acción (
groupBy().sum("Ventas")
): Calculamos el total de ventas de los productos filtrados. - Detener la sesión de Spark: Cerramos la sesión de Spark.
- Resumen
En esta sección, hemos aprendido sobre la estructura y ejecución de trabajos en Apache Spark. Hemos cubierto conceptos clave como trabajos, etapas y tareas, y hemos visto cómo Spark organiza y ejecuta estos trabajos utilizando un DAG. Además, hemos trabajado con ejemplos prácticos para reforzar estos conceptos.
En el próximo módulo, exploraremos cómo utilizar caché y persistencia para optimizar el rendimiento de nuestras aplicaciones Spark.
Curso de Apache Spark
Módulo 1: Introducción a Apache Spark
Módulo 2: Conceptos Básicos de Spark
- RDDs (Conjuntos de Datos Distribuidos Resilientes)
- Transformaciones y Acciones
- DataFrames de Spark
- Spark SQL
Módulo 3: Procesamiento de Datos con Spark
Módulo 4: Programación Avanzada en Spark
Módulo 5: Ajuste y Optimización del Rendimiento
- Entendiendo los Trabajos de Spark
- Caché y Persistencia
- Gestión de Memoria
- Optimizando Aplicaciones Spark
Módulo 6: Spark en la Nube
- Ejecutando Spark en AWS
- Ejecutando Spark en Azure
- Ejecutando Spark en Google Cloud
- Spark con Kubernetes
Módulo 7: Aplicaciones del Mundo Real y Estudios de Caso
- Procesamiento de Datos en Tiempo Real
- Analítica de Big Data
- Pipelines de Aprendizaje Automático
- Estudios de Caso