Preguntas de entrevistas para SparkCore

1. Escriba WordCount (lea un archivo local) y empaquételo en el clúster para ejecutarlo, explicando los parámetros principales que deben agregarse.

Código

	val conf: SparkConf = new SparkConf().setAppName(this.getClass.getName)
    val sc = new SparkContext(conf)
    val resRDD: RDD[(String, Int)] = sc.textFile(args(0)).flatMap(_.split(" ")).map((_, 1)).reduceByKey(_ + _)
    resRDD.saveAsTextFile(args(1))

    sc.stop()

Ejecute el comando jar:

bin/spark-submit \
--master yarn \
--deploy-mode client \
--executor-cores 2 \
--class com.aura.spark.day06.Spark09_Interview1 \
/home/hadoop/jar/WordCount.jar \
/word_in \
/word_out

Análisis de comandos

  • maestro: especifica el modo de funcionamiento del programa.
  • modo de implementación: especifique si el controlador se ejecuta en el clúster o localmente.
  • Ejecutor-cores: El número de núcleos para cada Ejecutor.
  • clase: el nombre completo de la clase principal del programa Spark.

2. Cinco características de RDD

  • Un conjunto de particiones;
  • Reglas de cálculo para los datos de cada partición;
  • Relación de la dependencia sanguínea con otros RDD;
  • Para los datos almacenados en tipo KV, hay un particionador opcional.
  • Almacene una lista de ubicaciones prioritarias para sectores.

3. Cómo crear un RDD, hay varias formas, por ejemplo

Cuatro tipos.

  • Método MakeRDD () o paralelize () para crear RDD;
  • textFile () lee el archivo para crear un RDD;
  • El operador de transformación genera un nuevo RDD a través de otros RDD;
  • Cree un RDD a través del nuevo método, como new JdbcRDD ().

4. Cree un RDD para convertir los datos de una partición en una cadena. Por ejemplo (Array ("a", "b", "c", "d"), 2) => ("ab", "cd")

	val conf: SparkConf = new SparkConf().setAppName(this.getClass.getName).setMaster("local[*]")
    val sc = new SparkContext(conf)
    val rdd: RDD[String] = sc.makeRDD(Array("a", "b", "c", "d"), 2)
    // 将同一分区数据转为数组
    val glomRDD: RDD[Array[String]] = rdd.glom()
    glomRDD.foreach(println)
    val resRDD: RDD[String] = glomRDD.map(
      arr => {
    
    
        arr.mkString("")
      }
    )
    resRDD.foreach(println)

    sc.stop()

5. La diferencia entre map y mapPartitions

  • map es un mapeo uno a uno de los elementos en el RDD de acuerdo con las reglas especificadas.
  • mapPartitons consiste en mapear los elementos en el RDD de acuerdo con las reglas especificadas en la unidad de partición.

6. El papel, la diferencia y la conexión de los dos operadores de fusión y repartición.

efecto

        Repartición.

contacto

        La capa inferior de las llamadas de repartición se fusionan, pero el parámetro shuffle se establece en verdadero, lo que significa que se realiza la repartición aleatoria.

la diferencia

        El parámetro de mezcla aleatoria predeterminado de coalesce es falso, lo que significa que no se realiza la distribución aleatoria de particiones, y generalmente se utiliza para reducir las particiones. La repartición se usa generalmente para aumentar las particiones.

7. A qué se debe prestar atención al usar el operador de cremallera (es decir, qué situaciones no se pueden usar)

  • En una colección scala, la función zip puede realizar una operación zip incluso si el número de elementos en las dos colecciones no es el mismo, pero los elementos adicionales no se devolverán.
  • Sin embargo, en el operador Spark RDD, el operador zip solo puede operar en dos RDD con el mismo número de particiones y elementos .

8. La diferencia entre reduceByKey y groupByKey

  • reduceByKey: Agregado de acuerdo con la clave . Antes de la reproducción aleatoria, los datos en la partición se agregarán previamente y el resultado devuelto es un RDD de tipo kv (RDD [K, V]).
  • groupByKey: Agrupa por tecla y realiza directamente la reproducción aleatoria . El resultado devuelto es un RDD de tipo k-iterador (RDD [K, Iterable [V]]).
  • Sin afectar la lógica empresarial, se prefiere reduceByKey. La operación de suma no afecta la lógica empresarial y la operación de promediado afecta la lógica empresarial.

9. La diferencia y la conexión entre reduceByKey, aggregateByKey y foldByKey

contacto

  • Todas las operaciones de agregación se realizan de acuerdo con la clave y los datos se agregan previamente antes de la reproducción aleatoria.

la diferencia

  • reduceByKey: no hay un valor inicial y las reglas de cálculo dentro y entre las particiones son las mismas.
  • aggregateByKey: hay un valor inicial, y el valor inicial participa en el cálculo dentro y entre particiones. Las reglas dentro y entre particiones pueden ser inconsistentes.
  • foldByKey: Hay un valor inicial, y el valor inicial participa en el cálculo dentro de la partición.Las reglas de cálculo dentro y entre las particiones son las mismas.

10. Función de parámetro de CombineByKey, explique su tiempo de llamada de parámetro

  • Parámetro 1: La estructura de los datos se puede convertir.
  • Parámetro 2: Reglas de cálculo dentro de la partición.
  • Parámetro 3: Reglas de cálculo entre particiones.

11. Varias formas de utilizar RDD para implementar Join

  • rdd1.join (rdd2): asocia los valores correspondientes a la misma clave. Si la clave es solo un determinado RDD, no se devolverá.
  • rdd1.leftOuterJoin (rdd2): devuelve todos los valores-clave en rdd1 y el valor-clave asociado.
  • rdd1.rightOuterJoin (rdd2): devuelve todos los valores-clave en rdd2 y el valor-clave asociado.
  • rdd1.cogroup (rdd2): Cada rdd primero asocia su propia clave para formar un conjunto y luego se fusiona.

12. La diferencia y la conexión entre aggregateByKey y aggregate

contacto

  • Ambos realizan operaciones de agregación en elementos dentro y entre particiones, y ambos tienen valores iniciales.

la diferencia

  • aggregateByKey es un operador de conversión, que opera en RDD de tipo kv. El valor inicial participa en los cálculos dentro y entre particiones. El valor inicial iterará y operará con cada elemento en el RDD.
  • Agregado es un operador de acción. El valor inicial participa en el cálculo dentro y entre particiones. Cuando se calcula dentro de una partición, el valor inicial y un elemento en cada partición del RDD se calculan de acuerdo con las reglas especificadas. Al calcular entre particiones, el El valor inicial solo participará en el cálculo una vez.

13. ¿Crear un RDD, personalizar una regla de partición e implementarla? ¿Se puede particionar Spark por valor?

Particionador personalizado

object Spark12_Interview13 {
    
    
  def main(args: Array[String]): Unit = {
    
    
    val conf: SparkConf = new SparkConf().setAppName(this.getClass.getName).setMaster("local[*]")
    val sc = new SparkContext(conf)
    val rdd: RDD[(String, String)] = sc.makeRDD(List(("13698624174", "河北"), ("13766887551", "广东"),
      ("13876543211", "上海"), ("17677885551", "河南")), 2)
    // 使用自定义分区器重新分区
    val resRDD: RDD[(String, String)] = rdd.partitionBy(new MyPartitoner(4))
    resRDD.mapPartitionsWithIndex{
    
    
      case (index, datas) => {
    
    
        println(index + "--->" + datas.mkString(","))
        datas
      }
    }.collect()
    sc.stop()
  }
}

// 自定义分区器
class MyPartitoner(partitons: Int) extends Partitioner {
    
    
  // 分区数量
  override def numPartitions: Int = partitons

  // 自定义分区逻辑
  override def getPartition(key: Any): Int = {
    
    
    val strKey: String = key.asInstanceOf[String]
    // 返回分区号
    if (strKey.startsWith("136")) 0
    else if (strKey.startsWith("137")) 1
    else if (strKey.startsWith("138")) 2
    else 3
  }
}

Partición por valor

  • RDD intercambia la posición del valor y la clave a través del mapeo del mapa.

14. Lea el archivo y realice la función WordCount. (Utilice diferentes operadores para lograr, al menos 3 formas)

método uno

    val rdd: RDD[String] = sc.textFile("D:\\develop\\workspace\\bigdata2021\\spark2021\\input\\word.txt")
     // 方式一
    val wordCountRDD: RDD[(String, Int)] = rdd.flatMap(_.split(" ")).map((_, 1)).reduceByKey(_ + _)

Camino dos

	val wordCountRDD: RDD[(String, Int)] = rdd.flatMap(_.split(" ")).map((_, 1)).groupByKey().map {
    
    
      case (key, datas) => {
    
    
        (key, datas.size)
      }
   	}

Camino tres

	val wordCountRDD: RDD[(String, Int)] = rdd.flatMap(_.split(" ")).groupBy(word => word).map {
    
    
      case (key, datas) => {
    
    
        (key, datas.size)
      }
    }

Camino cuatro

    val wordCountRDD: RDD[(String, Int)] = rdd.flatMap(_.split(" ")).map((_, 1)).aggregateByKey(0)(_+_,_+_)

Camino cinco

	val wordCountRDD: RDD[(String, Int)] = rdd.flatMap(_.split(" ")).map((_, 1)).foldByKey(0)(_+_)

Camino seis

	val wordCountRDD: RDD[(String, Int)] = rdd.flatMap(_.split(" ")).map((_, 1)).combineByKey(
      // 转换数据结构
      elem => elem,
      // 分区内计算规则
      (a: Int, b: Int) => {
    
    
        a + b
      },
      // 分区间计算规则
      (a: Int, b: Int) => {
    
    
        a + b
      }
    )

15. Cuénteme sobre su comprensión de la relación sanguínea RDD.

  • RDD genera una serie de RDD a través de operadores de conversión. Spark registrará la relación de dependencia entre cada RDD . Esta relación se llama relación de sangre. Puede ver la relación de sangre entre RDD a través del operador toDebugString.
  • Spark formará un gráfico acíclico dirigido por DAG basado en la relación sanguínea entre los RDD. Según este gráfico acíclico dirigido, Spark puede manejar de manera eficiente la tolerancia a fallas y la recuperación de datos .

16. ¿Cómo realiza Spark la segmentación de tareas? Explique los conceptos relacionados involucrados.

  • Aplicación: un programa Spark es una aplicación y una aplicación puede tener varios trabajos.
  • Trabajo de trabajo: activar un operador de acción es un trabajo y un trabajo puede tener varias etapas.
  • Etapa etapa: divida las diferentes etapas con amplia dependencia, el número de etapas = el número de amplias dependencias + 1. Un escenario puede tener múltiples tareas.
  • Tarea tarea: el número de particiones del último RDD de cada etapa = el número de tareas.

17. La diferencia y la conexión entre la caché RDD y checkPoint

contacto

  • Tanto el caché como el punto de control almacenan en caché los datos en el RDD, y el RDD con la misma lógica de cálculo puede obtener directamente los datos del caché sin volver a calcular.
  • Solo cuando se activa el operador de acción, la caché se almacenará realmente en caché.

la diferencia

  • El caché no cortará la relación de sangre del RDD. El caché se almacena en la memoria por defecto y se puede configurar para ser almacenado en el disco local. Sin embargo, los datos almacenados en caché por el caché se perderán a medida que se ejecuta el programa.
  • Checkpoint checkpoint cortará la relación sanguínea de RDD y puede almacenar datos en sistemas de almacenamiento de alta disponibilidad y alta confiabilidad como HDFS.
  • Para garantizar la precisión de los datos, cuando el punto de control se utilice por primera vez, se ejecutará de principio a fin de acuerdo con la relación de consanguinidad del RDD.
  • Generalmente, el punto de control y la caché se utilizan juntos.

18.Spark lee el mecanismo de corte predeterminado de archivos HDFS

  • Al crear un RDD, la ruta del archivo y el número mínimo de particiones minPartitions se pasan a HadoopRDD.
    Inserte la descripción de la imagen aquí

  • Llame al método getSplits en FileInputFormat para calcular la información del sector.
    Inserte la descripción de la imagen aquí

  • En primer lugar, calcule el tamaño objetivo de la porción metaSize: tamaño de la porción objetivo = tamaño del archivo / número mínimo de particiones.
    Inserte la descripción de la imagen aquí

  • Luego calcule el corte mínimo minSize: max (FileInputFormat.SPLIT_MINSIZE, minSplitSize), el mínimo es 1.
    Inserte la descripción de la imagen aquí

  • Luego calcule splitSize = Math.max (minSize, Math.min (goalSize, blockSize)), por lo que SplitSize es generalmente el mínimo de goalSize y blockSize.
    Inserte la descripción de la imagen aquí
    Inserte la descripción de la imagen aquí

  • Si el tamaño de archivo restante / splitSize> 1.1, corte una rebanada.
    Inserte la descripción de la imagen aquí

19. Cuénteme sobre su comprensión de las variables de transmisión.

  • Variable de difusión: variable de solo lectura compartida distribuida.
  • Cuando el programa Spark se está ejecutando, la función pasa a través del operador. Es posible que la función necesite acceder a la variable definida en el lado del Conductor. Spark enviará una copia de esta variable para cada tarea en el lado del Ejecutor. Si la variable es relativamente grande, se consumirá Más memoria en el lado del Ejecutor.
  • Si definimos la variable como una variable de difusión, Spark solo enviará una copia de la variable de difusión al lado del Ejecutor para que todas las tareas accedan.

20. Personalice un acumulador para realizar la función de conteo

Cuente el número de palabras que comienzan con H

object Spark14_Interview20 {
    
    
  def main(args: Array[String]): Unit = {
    
    
    val conf: SparkConf = new SparkConf().setAppName(this.getClass.getName).setMaster("local[*]")
    val sc = new SparkContext(conf)
    val rdd: RDD[String] = sc.makeRDD(List("Hello", "HaHa", "spark", "scala", "java", "Hive", "Hi"), 2)
    // 声明累加器
    val acc = new MyAccumulator20
    // 注册
    sc.register(acc, "myacc")
    // 使用
    rdd.foreach(datas => {
    
    
      acc.add(datas)
    })
    // 打印累加器中的值
    println(acc.value)

    sc.stop()
  }
}

// 自定义累加器  泛型为输入类型和输出类型
class MyAccumulator20 extends AccumulatorV2[String, Int] {
    
    
  var num = 0

  // 判断是否为初始值
  override def isZero: Boolean = {
    
    
    num == 0
  }

  // 复制累加器
  override def copy(): AccumulatorV2[String, Int] = {
    
    
    val MyAcc = new MyAccumulator20
    MyAcc.num = this.num
    MyAcc
  }

  // 重置累加器
  override def reset(): Unit = {
    
    
    num = 0
  }

  // 添加元素
  override def add(v: String): Unit = {
    
    
    if (v.startsWith("H")) {
    
    
      num += 1
    }
  }

  // 合并累加器
  override def merge(other: AccumulatorV2[String, Int]): Unit = {
    
    
    num = this.num + other.value
  }

  // 取值
  override def value: Int = num
}

Supongo que te gusta

Origin blog.csdn.net/FlatTiger/article/details/115136126
Recomendado
Clasificación