Desarrollo de macrodatos: Spark: comprenda los RDD comunes en un artículo

1. Cinco propiedades básicas

  • Una lista de particiones

  • Una función para calcular cada división

  • Una lista de dependencias de otros RDD

  • Opcionalmente, un particionador para RDD de valor-clave (por ejemplo, para decir que el RDD tiene particiones hash)

  • Opcionalmente, una lista de ubicaciones preferidas para calcular cada división (por ejemplo, ubicaciones de bloques para un archivo HDFS)

Esto está escrito en los comentarios en el código fuente del RDD, los cinco atributos característicos se presentan a continuación

1.1 Partición

Una partición es la unidad básica del conjunto de datos. Para RDD, cada fragmento será procesado por una tarea informática y determinará la granularidad de la informática paralela. El usuario puede especificar el número de fragmentos de RDD al crear el RDD, si no se especifica, se utilizará el valor predeterminado

1.2 Función calculada

Una función para calcular datos de partición. El cálculo de RDD en Spark se basa en fragmentos, y cada RDD implementará la función de cálculo para lograr este objetivo. La función de cálculo combina los iteradores y no necesita guardar los resultados de cada cálculo.

1.3 Dependencia

Hay dependencias entre RDD. Cada conversión de RDD generará un nuevo RDD, y las dependencias anteriores y posteriores (linaje) similares a la canalización se forman entre los RDD. Cuando se pierde parte de los datos de la partición, Spark puede volver a calcular los datos de la partición perdidos a través de esta dependencia, en lugar de volver a calcular todas las particiones del RDD

1.4 Particionador

Para key-valueel RDD, el posible dispositivo de partición ( Partitioner). Spark implementa dos tipos de funciones de fragmentación, una está basada en hash HashPartitionery la otra es RangePartitioner basada en el rango. Solo son posibles los RDD de valor-clave y el valor de los RDD que no son de Partitionervalor-clave Parititioneres Ninguno. PartitionerLa función determina el RDDnúmero de sus propios fragmentos y también determina el parent RDD Shufflenúmero de fragmentos al generar

1.5 Lugar de almacenamiento prioritario

Una lista que almacena cada Partitionubicación preferida (ubicación preferida). Para un HDFSarchivo, esta lista guarda la Partitionubicación de cada bloque. De acuerdo con el concepto de "mover datos y no computar", Sparkcuando se programan tareas, las tareas de computación se asignarán a la ubicación de almacenamiento de los bloques de datos a procesar.

2. Operadores comunes entre conversiones RDD

A partir de las RDDcaracterísticas básicas anteriores , los programas que a menudo se escriben en el trabajo son la creación RDD, RDDconversión, RDDejecución de operadores, creación de los pasos necesarios para que los datos correspondientes a los sistemas externos fluyan hacia el clúster Spark, como para los datos creados a partir de colecciones, generalmente utilizado en las pruebas, por lo que no entraré en detalles. RDDLa conversión corresponde a un operador especial llamado Transformationcarga diferida, y la acción corresponde a Transformationla operación que desencadena la ejecución, generalmente se envía a la colección, se imprime o devuelve un valor , además, es salida del clúster a otros sistemas, lo que tiene un término profesional Action.

2.1 Operadores de conversión comunes

El operador de conversión, es decir, la operación de conversión de un RDD a otro RDD, corresponde a algunas funciones de cálculo integradas, pero estas funciones se dividen en operadores de dependencia amplia y operadores de dependencia estrecha con o sin reproducción aleatoria.

2.1.1 La diferencia entre dependencia amplia y dependencia estrecha

Generalmente, hay dos tipos de artículos en línea. Uno es la definición de transporte, es decir, si una RDDpartición principal dependerá de varias particiones secundarias. El otro es para ver si hay alguna Shuffle, si hay Shuffleuna dependencia amplia, si no hay, es una dependencia estrecha. Punto espectral, el segundo es tomarse a sí mismo como propio, por lo que no tiene valor de referencia. 2.1.3 Cómo distinguir entre dependencia amplia y dependencia estrecha, puedes ver esto

2.1.2 Operadores comunes de dependencias amplias y estrechas

Operadores comunes de dependencia estrecha

map(func): Use func para cada elemento en el conjunto de datos, y luego devuelva un nuevo RDD filter(func): use func para cada elemento en el conjunto de datos, y luego devuelva un RDD que contenga elementos que hagan que func sea verdadero flatMap(func): similar a map, cada elemento de entrada se asigna a 0 o más elementos de salida mapPartitions(func): similar a map, pero map usa func en cada elemento, y mapPartitions usa func en toda la partición. Suponiendo que un RDD tiene N elementos y M particiones (N >> M), entonces la función del mapa se llamará N veces, y la función en mapPartitions se llamará solo M veces, procesando todos los elementos en una partición a la vez mapPartitionsWithIndex(func): con mapPartitions De manera similar, más información sobre el valor de índice de la partición

glom(): Forme cada partición en una matriz para formar un nuevo RDD tipo RDD [matriz [T]] sample(withReplacement, fraction, seed): operador de muestreo. Utilice la semilla aleatoria especificada (semilla) para muestrear aleatoriamente los datos del número de fracciones, con Reemplazo indica si los datos extraídos se reemplazan o no, verdadero es el muestreo con reemplazo y falso es el muestreo sin reemplazo.

coalesce(numPartitions,false): Sin reproducción aleatoria, generalmente se usa para reducir particiones

union(otherRDD): Encuentra la unión de dos RDD

cartesian(otherRDD):Producto cartesiano

zip(otherRDD): Combina dos RDD en un RDD de valor-clave. De forma predeterminada, el número de particiones y el número de elementos de los dos RDD son los mismos; de lo contrario, se lanzará una excepción.

La diferencia entre map y mapPartitions map : procesar una pieza de datos mapPartitionsa la vez: procesar una partición de datos a la vez, los datos solo se pueden liberar una vez que se completa el procesamiento de datos de la partición. Cuando los recursos son insuficientes, es fácil llevar a OOM. Práctica recomendada : cuando los recursos de memoria son suficientes, se recomienda utilizar mapPartitionsPara mejorar la eficiencia del procesamiento

Operadores comunes de amplia dependencia

groupBy(func): Agrupa según el valor de retorno de la función pasada. Ponga el mismo valor de clave en un iterador

distinct([numTasks])): Después de eliminar los duplicados del elemento RDD, devuelve un RDD nuevo. Puede pasar el parámetro numTasks para cambiar el número de particiones RDD

coalesce(numPartitions, true): Con la reproducción aleatoria, ya sea para aumentar o disminuir las particiones, generalmente use repartición en su lugar

repartition(numPartitions): Aumenta o disminuye el número de particiones, con reproducción aleatoria

sortBy(func, [ascending], [numTasks]): Use func para procesar los datos y ordenar los resultados procesados

intersection(otherRDD): Encuentra la intersección de dos RDD

subtract (otherRDD): Encuentra la diferencia de dos RDD

2.1.3 Cómo distinguir entre dependencia amplia y dependencia estrecha

Aquí sugiero operadores que no se pueden entender. Desde Sparkel historygráfico de dependencia, vea Stagesi hay alguna división . Si está dividido , es una dependencia amplia, y si no está dividido , es una dependencia estrecha. Por supuesto, esta es una práctica Puedes explicar el problema a tus colegas o compañeros de clase. Cuando sea el momento, show your codedáselo y luego dale el gráfico de dependencia. Por supuesto, como un paralelo de la teoría y la práctica, usaré otro método para juzgar. comienza por comprender la definición. La definición dice si la partición RDD principal está dividida por varios elementos secundarios. La dependencia de la partición, puede pensar en ello desde esta perspectiva, ¿es posible que los datos en una sola partición de la partición principal fluyan al partición de diferentes RDD secundarios, por ejemplo, piense en el operador distinto, o el operador sortBy, la deduplicación global y la ordenación global, asumiendo que al principio 1, 2 y 3 están en una partición. Después de la map(x => (x, null)).reduceByKey((x, y) => x).map(_._1)deduplicación, aunque el número de particiones no ha cambiado, los datos de cada partición deben ser leídos por los datos de otras particiones para saber si mantenerlos al final, desde la partición de entrada a la partición de salida., después de la inevitable convergencia de la reestructuración , por lo que debe haber shuffleuna . sortBySimilar.

2.2 Operadores de acción común

La acción activa Job. Un programa Spark (programa de controlador) contiene tantos operadores de acción como trabajos; operadores de acción típicos: recopilar / contar recopilar () => sc.runJob () => ... => dagScheduler.runJob () => El trabajo es desencadenado

collect() / collectAsMap() stats / count / mean / stdev / max / min reduce(func) / fold(func) / aggregate(func)

first(): Devuelve el primer elemento de este RDD take(n): Toma el primer número de elementos del RDD top(n): De acuerdo con las reglas de clasificación predeterminadas (orden descendente) o especificadas, devuelve el primer número de elementos. takeSample(withReplacement, num, [seed]): Devuelve datos muestreados foreach(func) / foreachPartition(func): similar a map y mapPartitions, la diferencia es que foreach es ActionsaveAsTextFile(path) / saveAsSequenceFile(path) / saveAsObjectFile(path)

3. Operaciones comunes de PairRDD

RDD generalmente se divide en tipo de valor y tipo de valor-clave. La introducción anterior es la operación de RDD de tipo Value, el uso real es más RDD de tipo clave-valor, también conocido como PairRDD. Las operaciones RDD de tipo Value se concentran básicamente en RDD.scala, las operaciones RDD de tipo key-value se concentran en PairRDDFunctions.scala;

La mayoría de los operadores introducidos anteriormente son válidos para Pair RDD. Cuando el valor de RDD es clave-valor, se puede convertir implícitamente a PairRDD. Pair RDD también tiene sus propios operadores de Transformación y Acción;

archivo

3.1 Operaciones de transformación de PairRDD común

3.1.1 Operaciones de mapas similares

mapValues ​​/ flatMapValues ​​/ keys / values, estas operaciones se pueden implementar usando operaciones de mapa, que son operaciones simplificadas.

3.1.2 Operación de agregación [importante y difícil]

PariRDD (k, v) tiene una amplia gama de aplicaciones, agregado groupByKey / reduceByKey / foldByKey / aggregateByKey combineByKey (OLD) / combineByKeyWithClassTag (NEW) => la implementación subyacente subtractByKey: similar a restar, elimine la clave en el RDD que es el igual que la clave en otro elemento RDD

Conclusión : use el método más familiar para lograr la misma eficiencia; groupByKey es generalmente ineficiente, así que use la menor cantidad posible

3.1.3 Operación de clasificación

sortByKey: la función sortByKey actúa en PairRDD para ordenar la clave

3.1.4 operación de unión

cogroup / join / leftOuterJoin / rightOuterJoin / fullOuterJoin

archivo

val rdd1 = sc.makeRDD(Array((1,"Spark"), (2,"Hadoop"), (3,"Kylin"), (4,"Flink")))
val rdd2 = sc.makeRDD(Array((3,"李四"), (4,"王五"), (5,"赵六"), (6,"冯七")))
val rdd3 = rdd1.cogroup(rdd2)
rdd3.collect.foreach(println)
rdd3.filter{case (_, (v1, v2)) => v1.nonEmpty & v2.nonEmpty}.collect
// 仿照源码实现join操作
rdd3.flatMapValues( pair =>
for (v <- pair._1.iterator; w <- pair._2.iterator) yield (v, w)
)
val rdd1 = sc.makeRDD(Array(("1","Spark"),("2","Hadoop"),("3","Scala"),("4","Java")))
val rdd2 = sc.makeRDD(Array(("3","20K"),("4","18K"),("5","25K"),("6","10K")))
rdd1.join(rdd2).collect
rdd1.leftOuterJoin(rdd2).collect
rdd1.rightOuterJoin(rdd2).collect
rdd1.fullOuterJoin(rdd2).collect

3.1.5 Operación de acción

collectAsMap / countByKey / lookup(key)

archivo

lookup(key): Método de búsqueda eficiente, solo busca los datos correspondientes a la partición (si el RDD tiene un particionador)

4. Mensaje

Conocimiento real del combate real, cuando quieres una cierta comprensión, suponga que piensa en cierto operador, luego lo usa, mira el código fuente donde no entiende, ¡y tendrá éxito! Wu Xie, Xiao San Ye, un pequeño novato en segundo plano, big data e inteligencia artificial. Presta atención a másarchivo

Supongo que te gusta

Origin blog.csdn.net/hu_lichao/article/details/112134716
Recomendado
Clasificación