Sintonización de tecnología Spark, ¿no me digas que no puedes?

Tabla de contenido

 

Uno, ajuste de rendimiento

Dos, tuning jvm 

3. Sintonización aleatoria (use los dos primeros puntos primero, la medición real es efectiva)

Cuarto, ajuste del operador

五 、 solución de problemas

Seis, solución de inclinación de datos


Uno, ajuste de rendimiento

1.1 Con más recursos:

    --num-ejecutores 3 \ Configure el número de ejecutores --driver-memory 100m \ Configure la memoria del controlador (con poco impacto) --executor-memory 100m \ Configure el tamaño de la memoria de cada ejecutor --executor-cores 3 \ Configure cada La cantidad de núcleos de CPU de cada ejecutor

    núm-ejecutores y núcleos ejecutores pueden mejorar el paralelismo de las tareas; la memoria del controlador y la memoria del ejecutor aumentan la memoria, lo que puede almacenar en caché más datos, reducir la E / S del disco, reducir la E / S del disco lateral durante la subflujo y reducir la GC frecuente cuando la memoria del montón está llena Para evitar la recolección frecuente de basura

1.2 Ajustar el grado de paralelismo:

    1. El número de tareas, al menos configurado para ser el mismo que el número total de núcleos de CPU de la aplicación Spark (la situación más ideal, por ejemplo, un total de 150 núcleos de CPU, 150 tareas se asignan, se ejecutan juntas y se ejecutan casi al mismo tiempo)

    2. La recomendación oficial es que el número de tareas se establece en 2 ~ 3 veces el número total de núcleos de CPU en la aplicación Spark, como 150 núcleos de CPU, el número de tareas se establece básicamente en 300 ~ 500;

    ¿Cómo establecer el paralelismo de una aplicación Spark? SparkConf conf = new SparkConf () .set ("spark.default.parallelism", "500")

1.3 Refactorizar la arquitectura RDD y la persistencia RDD:

    En primer lugar, la reconstrucción y optimización de la arquitectura RDD intenta reutilizar RDD, se pueden extraer RDD similares y denominar RDD común para su uso repetido en cálculos posteriores de RDD.

    En segundo lugar, los RDD públicos deben persistir y los RDD públicos que deben calcularse y utilizarse varias veces deben persistir.

    En tercer lugar, la persistencia se puede serializar. Optimice el uso de la memoria, luego considere el disco

    Cuarto, para una alta confiabilidad de los datos y suficiente memoria, se puede usar el mecanismo de doble copia para la persistencia; después de una copia de persistencia, debido a que la máquina está inactiva y la copia se pierde, se debe recalcular; de esta manera Camino, solo para sus recursos de memoria extremadamente suficientes

1.4 Difusión de grandes variables

    El beneficio de difundir variables no es una copia de cada tarea, sino una copia del ejecutor de cada nodo. De esta forma, se puede reducir considerablemente el número de copias de variables. Reduzca la sobrecarga de la red, el uso de memoria, E / S de disco, tiempos de recolección de basura GC

1.5 使用 Kryo 序列 化 conjunto ("spark.serializer", "org.apache.spark.serializer.KryoSerializer")

    Spark utiliza internamente el mecanismo de serialización de Java, ObjectOutputStream / ObjectInputStream, el mecanismo de flujo de entrada y salida de objetos para serializar

    Spark admite el uso del mecanismo de serialización de Kryo. El mecanismo de serialización de Kryo es más rápido que el mecanismo de serialización de Java predeterminado, y los datos serializados son más pequeños, que es aproximadamente 1/10 del mecanismo de serialización de Java. Por lo tanto, una vez optimizada la serialización de Kryo, los datos transmitidos en la red se pueden reducir; los recursos de memoria consumidos en el clúster se reducen considerablemente.

1.6 Utilice fastutil para optimizar el formato de datos

    fastutil intenta proporcionar la biblioteca de colecciones más rápida en cualquier escenario

1.7 Ajustar el tiempo de espera para la localización de datos

    BlockManager> PROCESS_LOCAL> NODE_LOCAL> NO_PREF> RACK_LOCAL> ANY    

    Observe el registro y el registro en ejecución del trabajo de Spark. Se recomienda que utilice el modo cliente primero cuando realice la prueba, y puede ver directamente el registro relativamente completo localmente. El registro mostrará, comenzando la tarea. . . , PROCESO LOCAL, NODO LOCAL Observe el nivel de localización de datos de la mayoría de las tareas

    new SparkConf () .set ("spark.locality.wait", "10") 

BlockManager

Ubicación de almacenamiento

Descripción detallada

PROCESS_LOCAL

Localización de procesos 

Los datos a calcular por la tarea están en el mismo Ejecutor

NODE_LOCAL

Localización de nodos  

La velocidad es un poco más lenta que PROCESS_LOCAL, porque los datos deben pasarse entre diferentes procesos o leerse desde un archivo.

NO_PREF

No hay mejor posicion

Se accede a los datos tan rápido desde donde se encuentren, no se requiere prioridad de ubicación. Por ejemplo, SparkSQL lee datos en MySQL

RACK_LOCAL

Localización

Los datos están en diferentes nodos en el mismo rack. Necesita transferir datos y archivar IO a través de la red, más lento que NODE_LOCAL

ALGUNA

Estante cruzado

Los datos son los más lentos en una red que no sea el mismo rack


Dos, tuning jvm 

2.1 Ajuste de JVM para reducir la proporción de memoria de las operaciones de caché

    El primer punto del ajuste de JVM: reducir la relación de memoria de las operaciones de caché En Spark, la memoria de pila se divide en dos partes, una parte se usa para el almacenamiento en caché de datos RDD para operaciones de caché RDD y persistencia;

    Otra pieza, que acabamos de mencionar, se utiliza para la operación de las funciones del operador de chispa y almacena los objetos creados por la función.

    spark.storage.memoryFraction , 0.6 -> 0.5 -> 0.4 -> 0.2

2.2 El ajuste de JVM ajusta la memoria fuera del montón del ejecutor y el tiempo de espera de la conexión

    --conf spark.yarn.executor.memoryOverhead = 2048 (mínimo 300 m), generalmente más grande

    --conf spark.core.connection.ack.wait.timeout = 300 (archivo XX, no encontrado. Archivo perdido. Es muy probable que el ejecutor con los datos esté en el jvm gc. Por lo tanto, cuando se extraen los datos, no se puede establecer Conéctese. Luego, después de los 60 predeterminados, fallará directamente).


3. Sintonización aleatoria (use los dos primeros puntos primero, la medición real es efectiva)

3.1 Ajuste aleatorio para fusionar archivos de salida de mapas

    new SparkConf (). set ("spark.shuffle.consolidateFiles", "true") activa el mecanismo de fusión aleatoria de archivos de salida del lado del mapa; de forma predeterminada, no está activado, es decir, se producirá una gran cantidad de archivos de salida del lado del mapa como se describe anteriormente La operación afecta gravemente al rendimiento.

    Si no está activado, se creará un archivo para cada tarea, y cuántos archivos se generarán antes y después de que se cree la tarea; si está activado, se generará el paralelismo de la tarea * número de ejecutores.

3.2 La sintonización aleatoria ajusta la relación del búfer de memoria en el lado del mapa y la memoria en el lado de reducción

    spark.shuffle.file.buffer, 32k predeterminado, se puede ajustar a 64K // spark.shuffle.file.buffer, duplicado cada vez, y luego ver el efecto, 64, 128; spark.shuffle.memoryFraction, aumentar en 0.1 cada vez Para ver el efecto.

    spark.shuffle.memoryFraction, el valor predeterminado es 0.2, se puede ajustar a 0.3 // Si la cantidad de datos es grande y la tarea de reducción extrae muchos datos, entonces la memoria agregada del lado de reducción no es suficiente, operaciones de derrame frecuentes, escritura de desbordamiento Sube el disco.

3.3 Ajuste aleatorio de HashShuffleManager y SortShuffleManager

  1. En un entorno de producción, no se recomienda que utilice el tercer y cuarto punto precipitadamente:
  2. Si no desea que sus datos se clasifiquen durante la reproducción aleatoria, configúrelo usted mismo y use el administrador de reproducción aleatoria de hash. 
  3. Si realmente necesita que sus datos se clasifiquen durante la reproducción aleatoria, no es necesario que los cambie de forma predeterminada. El valor predeterminado es el administrador de clasificación aleatoria; ¿o qué? Si no le importa la clasificación en absoluto, déjelo que ordene por defecto. Ajuste algunos otros parámetros (mecanismo de consolidación). (80%, todos usan esto) 
    spark.shuffle.manager:hash、sort、tungsten-sort 
    new SparkConf().set("spark.shuffle.manager", "hash") 
    new SparkConf().set("spark.shuffle.manager", "tungsten-sort") 
    // 默认就是,new SparkConf().set("spark.shuffle.manager", "sort") 
    new SparkConf().set("spark.shuffle.sort.bypassMergeThreshold", "550")

Cuarto, ajuste del operador

4.1 MapPartitions mejora el rendimiento de las operaciones del mapa

    ¿Cuándo es adecuado utilizar la serie de operaciones MapPartitions, es decir, cuando la cantidad de datos no es particularmente grande, puede utilizar esta serie de operaciones MapPartitions, el rendimiento sigue siendo muy bueno y hay una mejora? Por ejemplo, fueron 15 minutos (hubo un ajuste de rendimiento), 12 minutos. 10 minutos -> 9 minutos.

4.2 Use coalesce para reducir el número de particiones después del filtro

    Se utiliza principalmente para comprimir el número de particiones cuando el volumen de datos de cada partición es diferente después de la operación de filtrado. Reduzca el número de particiones y haga que el volumen de datos de cada partición sea lo más uniforme y compacto posible. Esto es conveniente para que las tareas posteriores realicen operaciones de cálculo y puede mejorar el rendimiento hasta cierto punto.

4.3 Utilice foreachPartition para optimizar el rendimiento de la base de datos de escritura

    En el entorno de producción real, se utiliza toda la operación foreachPartition; pero hay un problema, como la operación mapPartitions, si el número de particiones es realmente muy grande, como 1 millón, básicamente no es confiable Arriba. Entra de repente, OOM, es probable que se produzcan problemas de desbordamiento de memoria.

4.4 Usar repartición para resolver el problema de rendimiento del paralelismo bajo de Spark SQL

    El operador de repartición, el paralelismo y la cantidad de tareas que usa en este paso de Spark SQL, no debe haber forma de cambiarlo. Sin embargo, puede usar el operador de repartición para reparticionar el RDD que consultó con Spark SQL. En este momento, puede particionar en varias particiones, por ejemplo, de 20 particiones a 100 particiones.

4.5 agregación local reduceByKey

    ReduceByKey, en comparación con las operaciones de reproducción aleatoria ordinarias (como groupByKey), una de sus características es que realizará la agregación local en el lado del mapa.


五 、 solución de problemas

5.1 Controlar el tamaño de la reproducción aleatoria reduce el búfer para evitar OOM

    El código de la función agregada ejecutada en el lado de reducción puede crear una gran cantidad de objetos. Quizás, de repente, la memoria no se mantendrá y será OOM. En este momento, se debe reducir el tamaño del búfer de tareas en el lado de reducción. Preferiría extraerlo varias veces, pero cada vez que puedo extraer el número de cada tarea en el lado de reducción al mismo tiempo, es relativamente pequeño y no es fácil provocar un desbordamiento de la memoria OOM. (Por ejemplo, se puede ajustar a 12 M)

    spark.reducer.maxSizeInFlight,48
    spark.reducer.maxSizeInFlight,24

5.2 Resuelva el error de extracción de archivos aleatorios causado por JVM GC

spark.shuffle.io.maxRetries 3

    El primer parámetro significa que cuando se extrae el archivo aleatorio, si no se extrae (la extracción falla), como máximo o algunas veces de reintento (el archivo se extraerá varias veces), el valor predeterminado es 3 veces. 

    spark.shuffle.io.retryWait 5s El segundo parámetro significa que el intervalo de tiempo para cada reintento para extraer el archivo, el valor predeterminado es 5s.

5.3 Resuelva el error de la aplicación causado por recursos de cola YARN insuficientes

    Se puede enviar el mismo trabajo al mismo tiempo y el trabajo anterior ocupa el 60% de los recursos. Si vuelve a enviar el mismo trabajo, no habrá recursos suficientes o se enviará un trabajo largo y el trabajo debe ejecutarse durante 2 minutos más tarde.

    Solución: comunicarse con operación y mantenimiento para implementar estrategias de programación. Zeus

5.4 Resolver errores causados ​​por varias serializaciones

    Tres puntos a tener en cuenta sobre los errores de serialización: 

  1. En su función de operador, si se utiliza una variable de tipo personalizado externo, entonces, en este momento, su tipo personalizado debe ser serializable
  2. Si desea un tipo personalizado como tipo de elemento de RDD, entonces el tipo personalizado también debe ser serializable
  3. No se pueden utilizar algunos tipos de terceros que no admiten la serialización en los dos casos anteriores

    La conexión no admite la serialización

5.5 Resolver el problema causado por la función del operador que devuelve NULL

    Como puede ver, en algunas funciones de operador, necesitamos tener un valor de retorno. Sin embargo, a veces, es posible que no queramos devolver un valor para ciertos valores.

    Si devolvemos NULL directamente, lamentablemente podemos decirle que no funcionará y se informará un error. Scala.Math (NULL), si encuentra una excepción, realmente no desea devolver un valor para algún valor, hay una solución: 

  1. Cuando regrese, devuelva algunos valores especiales, no devuelva nulos, como "-999" 
  2. Después de obtener un RDD a través de un operador, puede realizar una operación de filtrado en este RDD para filtrar datos. En el filtro, los datos se pueden juzgar. Si es -999, devolverá falso y lo filtrará. 
  3. No olvides que el operador coalesce en el ajuste del operador del que hablamos antes, después del filtro, puedes usar el operador coalesce para comprimir el número de particiones RDD para hacer que los datos de cada partición sean más compactos. También puede mejorar un poco el rendimiento.

5.6 Resolver el problema del aumento de tráfico de la tarjeta de red causado por el modo de cliente de hilo

    En el modo de cliente de hilo, solo se utiliza para realizar pruebas;

    El modo de grupo de hilos no tiene nada que ver con el aumento del tráfico de tarjetas de red causado por su máquina local. En otras palabras, incluso si hay un problema, debe ser un asunto entre el equipo de operación y mantenimiento del hilo y el equipo de operación y mantenimiento básico.

    Después de usar el modo de agrupación de hilos, no es su máquina local ejecutar el controlador para la programación de tareas. En un grupo de hilos, un nodo ejecutará el proceso del controlador y será responsable de la programación de tareas.

5.7 Resuelva el problema del desbordamiento de la memoria de pila de JVM en modo de clúster de hilos

    En el modo de cliente de hilo, el controlador se ejecuta en la máquina local y el tamaño de la generación permanente de la JVM es 128 M. Esto no es un problema.

    En el modo de grupo de hilos, el controlador se ejecuta en un nodo del grupo de hilos y utiliza la configuración predeterminada (tamaño de generación permanente de PermGen) que no se ha configurado, 82M.

    Solución: en la secuencia de comandos Spark-Submit, agregue la siguiente configuración: --conf spark.driver.extraJavaOptions = "- XX: PermSize = 128M -XX: MaxPermSize = 256M"

    Problema 2: Spark sql tiene demasiados niveles de método para llamar, porque genera una gran cantidad de niveles muy profundos, que exceden el límite de la profundidad de pila de JVM, de forma recursiva.

    Solución: desbordamiento de memoria de pila de JVM, desbordamiento de memoria de pila. En este momento, se recomienda no participar en declaraciones sql de chispa tan complicadas. Utilice una solución alternativa: desmonte una instrucción SQL en varias instrucciones SQL para su ejecución. Cada instrucción SQL tiene solo 100 o cláusulas; cada instrucción SQL se ejecuta. De acuerdo con la prueba de la experiencia del entorno de producción, una declaración SQL, dentro de 100 o cláusulas, está bien. En circunstancias normales, no se informará del desbordamiento de la memoria de pila.

5.8 Modo de persistencia incorrecto y uso del punto de control


Seis, solución de inclinación de datos

6.1 Agregar datos de origen y claves de filtro que provocan sesgos

  • El primer esquema: datos de origen agregados; agrupar datos por clave, valor agregado y usar separadores para empalmar en el medio
  • La segunda solución: filtrar la clave que causa sesgo

    sencillo. directo. El efecto es muy bueno. Erradica por completo el problema de la desviación de datos.

6.2 Mejorar el paralelismo de reducir en operaciones de barajado

    Todos los operadores de reproducción aleatoria, como groupByKey, countByKey, reduceByKey. Al llamar, pase un parámetro. Un número. Ese número representa el paralelismo del lado de reducción de la operación aleatoria. Luego, cuando se realiza la operación de reproducción aleatoria, se creará correspondientemente un número específico de tareas de reducción. De esta forma, se pueden asignar menos datos a cada tarea de reducción. Básicamente, puede aliviar el problema de la desviación de datos.

    Por ejemplo, una tarea originalmente asignó una gran cantidad de datos, directamente OOM, la memoria se desbordó, el programa no se pudo ejecutar y simplemente se cuelga. De acuerdo con el registro, encuentre la operación de reproducción aleatoria con sesgo de datos y pase un número de grado paralelo. En este caso, los datos asignados a la tarea original definitivamente disminuirán. Al menos se puede evitar la situación OOM y el programa al menos se puede ejecutar.

6.3 Uso de claves aleatorias para lograr una doble agregación

    En la primera ronda de agregación, las claves se dividen y las claves originales se cambian a claves diferentes, lo que equivale a dividir cada clave en varios grupos; 

    Primero, realice la agregación local de claves para varios grupos; luego, elimine el prefijo de cada clave y luego realice la agregación global para todas las claves. 

    El sesgo de datos causado por groupByKey y reduceByKey tiene un mejor efecto. 

    Si la primera, segunda y tercera soluciones anteriores no pudieron resolver el problema de la desviación de datos, entonces solo puede confiar en este método.

6.4 Convertir combinación de reducción en combinación de mapa

    Si se van a unir dos RDD, uno de los RDD es relativamente pequeño. Un RDD es 1 millón de datos y un RDD es 10,000 datos. (Un RDD es 100 millones de datos y un RDD es 1 millón de datos) 

    Uno de los RDD debe ser relativamente pequeño. Después de que se difundan los datos de ese RDD pequeño, una copia residirá en el administrador de bloques de cada ejecutor. Asegúrese de tener suficiente memoria para almacenar los datos en ese pequeño RDD 

    De esta forma, no se producirá ninguna operación de mezcla y ciertamente no se producirá ningún sesgo de datos, fundamentalmente, se elimina el problema del sesgo de datos que puede ser causado por la operación de unión; 

    En el caso de que exista un sesgo de datos en la combinación, tratamos de considerar este método lo antes posible, el efecto es muy bueno; si un determinado RDD es relativamente pequeño.

6.5 Llave de inclinación de muestreo de muestra para unir por separado

    Extraiga la clave que tiene datos sesgados por separado y colóquela en un RDD; solo use este RDD clave que se habría inclinado y únase a otros RDD por separado. En este momento, los datos correspondientes a la clave pueden estar dispersos a muchos Unir la operación en una tarea. 

    No hace falta decir que cuando esta clave se mezcla con otras claves en un RDD, definitivamente hará que todos los datos correspondientes a una clave vayan a una tarea, lo que provocará un sesgo de datos.

6.6 Unir usando números aleatorios y tablas de expansión

  1. Para seleccionar un RDD, use flatMap para expandir la capacidad, mapee cada pieza de datos en múltiples piezas de datos, y cada dato mapeado va acompañado de un número aleatorio dentro de n. Generalmente, se selecciona 10. 
  2. Realice una operación de mapeo de mapa normal en otro RDD, y cada dato se marcará con un número aleatorio dentro de 10. 
  3. Finalmente, une los dos RDD procesados.

 

Supongo que te gusta

Origin blog.csdn.net/weixin_32265569/article/details/109267815
Recomendado
Clasificación