Introducción a las particiones de Apache Spark: todo cuanto necesita saber

Introducción a las particiones de Apache Spark: todo cuanto necesita saber

  • Lokesh Poojari Gangadharaiah
    Lokesh Poojari G is a Customer Success Architect at Talend. His field of expertise include Integration technologies , Project management & other programming languages. He has over 15 yrs work experience spanning organizations like Accenture, Thomson Financials, MetricStream etc in GRC, Telecom, Investments, Mobility & Media domains. He is Certified Scrum Master and has worked in the roles Senior Solution Architect, Delivery Manager, Product Manager & Business Analyst for various IT programs prior to joining Talend.

Los Conjuntos de datos distribuidos y resilientes (RDD, en inglés) de Apache Spark son un grupo de datos diversos de tamaño tan voluminoso que no caben en un único nodo y deben dividirse en particiones entre distintos nodos. Apache Spark divide automáticamente los RDD y reparte las particiones por distintos nodos. Se evalúan de forma perezosa (es decir, la ejecución no empieza hasta que se provoque una acción, lo que aumenta la facilidad de gestión, ahorra computación y con ello incrementa la optimización y la velocidad) y las transformaciones se almacenan como grafos acíclicos dirigidos (DAG, en inglés). Así pues, cada acción sobre los RDD obligará a Apache Spark a recomputar los DAG.

Es importante entender las características de las particiones en Apache Spark para que nos orienten y logremos un mejor rendimiento, depuración y manejo de los errores.

He aquí algunos conceptos básicos sobre las particiones:

  • Todos los nodos de un clúster de Spark contienen una o varias particiones.
  • El número de particiones que utiliza Spark es configurable y no es aconsejable tener demasiadas particiones (hace que se dedique más tiempo a la programación de tareas que a la ejecución en sí) ni demasiado pocas (genera menor concurrencia, sesgo en los datos y un uso indebido de los recursos). Por defecto, están configuradas al número total de núcleos de todos los nodos ejecutores.
  • Las particiones en Spark no abarcan más de una máquina.
  • Se garantiza que las tuplas de una misma partición estarán todas en la misma máquina.
  • Spark asigna una tarea por partición y cada trabajador puede procesar una tarea cada vez.

Particiones por hash o por range en Apache Spark

Apache Spark es compatible con dos tipos de particiones, llamadas "hash" o "range". La forma en la que estén distribuidas o secuenciadas las claves en sus datos y la acción que desee ejecutar sobre sus datos le ayudarán a escoger las técnicas más adecuadas. Son muchos los factores que condicionan la elección de particiones, como por ejemplo:

  • Recursos disponibles: número de núcleos sobre los que puede ejecutarse una tarea.
  • Fuentes de datos externas: el tamaño de las compilaciones locales, la tabla de Cassandra o el archivo de HDFS determinarán la cantidad de particiones.
  • Transformaciones utilizadas para derivar RDD: existen varias reglas para determinar el número de particiones cuando un RDD se deriva de otro RDD.

Como ven, son varios los aspectos que deben recordarse cuando se trabaja con Apache Spark. En este artículo me gustaría subrayar la importancia de conocer nuestros datos de empresa a la perfección, sus claves y recursos físicos para el procesamiento en Spark; quizá los más importantes sean la red, la CPU y la memoria.

Analicemos algunos de los errores más habituales que se cometen al trabajar con las particiones de Apache Spark:

Datos sesgados y bloques barajados

Procesar con particiones de Apache Spark por defecto puede provocar un sesgo en los datos que, a su vez, puede causar problemas relacionados con el barajado durante las operaciones de agregación o que los ejecutores únicos no tengan suficiente memoria.

Ejemplo de datos sesgados

En este ejemplo vemos que “key-a” tiene una cantidad mayor de datos en la partición, de modo que las tareas de Exec-5 tardarán mucho más en completarse que las otras cinco. Otra cosa importante que debemos recordar es que los bloques de barajado de Spark no pueden superar los 2 GB (internamente, porque la abstracción ByteBuffer tiene un MAX_SIZE configurado en 2 GB). Por ejemplo, si está ejecutando una operación como pueden ser unas agregaciones, JOINs u operaciones de caché, se producirá un barajado de Spark y tener pocas particiones o sesgos de datos puede dar un problema importante con el bloque de barajado. Por ello, si ha empezado a observar un error relativo a la superación de los límites de MAX_SIZE debido al barajado, ahora ya sabrá a qué es debido, ya que puede estar relacionado con el sesgo de los datos.

Particiones inteligentes

Entonces, ¿cómo se evitan los datos sesgados y los bloques de barajado? Creando particiones inteligentes. Resulta fundamental dividir correctamente en particiones para administrar la presión sobre la memoria y garantizar que se utilizan todos los recursos en los nodos del ejecutor. Debe conocer siempre sus datos: tamaño, tipos y su distribución. Un par de mejores prácticas a recordar son:

  • Entender y elegir los operadores adecuados para acciones como reduceByKey o aggregateByKey para que su controlador no reciba demasiada presión y las tareas se ejecuten correctamente en los ejecutores.
  • Si sus datos llegan en varios archivos grandes indivisibles, puede suceder que la división en particiones dictada por el InputFormat coloque grandes cantidades de registros en cada partición, sin generar suficientes particiones para aprovechar todos los núcleos disponibles. En este caso, invocar un reparto con un elevado número de particiones después de cargar los datos permitirá que las operaciones posteriores aprovechen más la CPU del clúster.
  • Además, si los datos están sesgados, también es aconsejable volver a dividir en particiones con la clave adecuada, que puede repartir la carga de forma más uniforme.

Talend proporciona un componente tPartition para los casos en que deban volver a dividirse las particiones conforme a las claves más adecuadas que usted elija.

¿Cómo se sabe cuál es el número adecuado de particiones?

Apache Spark tan solo puede ejecutar una única tarea concurrente para cada partición de un RDD, hasta el número de núcleos de su clúster (y probablemente el doble o el triple). Por ello, a la hora de elegir el número "adecuado" de particiones, lo normal es como mínimo tantas como ejecutores para el paralelismo. Este valor computado se puede obtener invocando sc.defaultParallelism. En última instancia, el tamaño máximo de una partición viene limitado por la memoria disponible de un ejecutor.

También se dan casos en los que no es posible entender qué clave de repartición es la más adecuada para una distribución de datos uniforme. Por ello, se puede recurrir a métodos como el salting, que implica añadir una nueva clave "falsa" y utilizarla junto con la clave actual para mejorar la distribución de los datos. Aquí tenemos un ejemplo:

  • Añada un elemento aleatorio a un RDD grande y cree también una nueva clave JOIN de esta manera: "clave de salting = clave JOIN real + clave falsa al azar, en la que la clave falsa asume un valor de 1 a N, donde N es el nivel de distribución"
  • Añada un elemento aleatorio a un RDD pequeño con un producto cartesiano (1-N) para aumentar la cantidad de entradas y crear una nueva clave JOIN.
  • Ahora los RDD JOIN de una nueva clave JOIN se distribuirán mejor debido al seeding aleatorio.
  • Elimine la clave falsa aleatoria de la clave JOIN para obtener el resultado final del JOIN.

En el ejemplo anterior, la clave falsa del conjunto de datos de consulta será un producto cartesiano (1-N) y, para el conjunto de datos principal, será una clave aleatoria (1-N) para los datos originales configurados en cada fila, y la N será el nivel de distribución.

Talend y Apache Spark

Talend Studio ofrece herramientas y asistentes gráficos que generan código nativo para que pueda empezar a trabajar con Apache Spark, Spark Streaming e incluso a dividir sus datos en particiones correctamente. Las técnicas mencionadas hasta aquí pueden implantarse por medio del componente tMap de Talend. También puede satisfacer sus necesidades en materia de nuevas particiones con el componente tPartition de Talend si conoce bien los datos y nuestro componente tMap para poner en práctica técnicas numéricas aleatorias y de salting para cuando le preocupa que los datos tengan claves sesgadas o valores nulos, según el caso.

Espero que con este breve artículo del blog haya aprendido algo nuevo sobre los rudimentos de las particiones y el procesamiento en Apache Spark. Para obtener más información sobre cómo funcionan juntos Talend y Apache Spark para mejorar la velocidad y la escala en el procesamiento de sus big data, puede consultar nuestra página de soluciones.

Referencias:

https://issues.apache.org/jira/browse/SPARK-6235

https://0x0fff.com/spark-architecture

https://www.youtube.com/watch?v=WyfHUNnMutg

http://blog.cloudera.com/blog/2015/05/working-with-apache-spark-or-how-i-learned-to-stop-worrying-and-love-the-shuffle/

http://blog.cloudera.com/blog/2015/03/how-to-tune-your-apache-spark-jobs-part-1/

https://stackoverflow.com/questions/40373577/skewed-dataset-join-in-spark

Join The Conversation

0 Comments

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *