Notas de estudo básico do Spark 20: persistência de RDD, nível de armazenamento e armazenamento em cache

Zero, os objetivos de aprendizagem desta palestra

  1. Entenda a necessidade de persistência de RDD
  2. Entendendo os níveis de armazenamento de RDDs
  3. Saiba como visualizar o cache RDD

1. Resistência RDD

(1) A necessidade de introduzir persistência

  • Os RDDs no Spark são carregados lentamente. Todos os RDDs são calculados do zero apenas quando um operador de ação é encontrado e, quando o mesmo RDD é usado várias vezes, ele precisa ser recalculado a cada vez, o que aumentará seriamente o consumo. Para evitar recalcular o mesmo RDD, o RDD pode ser persistido.
  • Uma das funções importantes no Spark é que os dados em um determinado RDD podem ser salvos na memória ou disco. Toda vez que uma operação do operador é necessária neste RDD, os dados persistentes deste RDD podem ser recuperados diretamente da memória ou disco. precisando calcular do zero para conseguir esse RDD.

(2) Operação de Persistência de Demonstração de Caso

1. Diagrama de dependência do RDD

  • Leia o arquivo, execute uma série de operações, existem vários RDDs, conforme mostrado na figura a seguir.
    insira a descrição da imagem aqui

2. Não use operações persistentes

  • Na figura acima, duas operações de operador são executadas em RDD3 para gerar RDD4 e RDD5, respectivamente. Se o RDD3 não for salvo de forma persistente, toda vez que você operar no RDD3, será necessário iniciar o cálculo de textFile(), converter os dados do arquivo em RDD1 e depois convertê-lo em RDD2 e, finalmente, obter RDD3.
  • Visualize o arquivo a ser manipulado
    insira a descrição da imagem aqui
  • Iniciar Spark Shell
    insira a descrição da imagem aqui
  • Siga o diagrama para obter RDD4 e RDD5
    insira a descrição da imagem aqui
  • Calcule RDD4, ele será executado de RDD1 a RDD2 a RDD3 a RDD4 e verifique o resultado
    insira a descrição da imagem aqui
  • Calcule RDD5 e também faça uma viagem de RDD1 para RDD2 para RDD3 para RDD4 para visualizar os resultados
    insira a descrição da imagem aqui

3. Use operações persistentes

  • Você pode usar o método persist() ou cache() no RDD para marcar o RDD a ser persistido (o método cache() na verdade chama o método persist() na parte inferior). Os dados serão computados na primeira ação e armazenados em cache na memória do nó. O cache do Spark é tolerante a falhas: se qualquer partição de um RDD armazenado em cache for perdida, o Spark recalculará automaticamente e armazenará em cache o processo de transformação original do RDD.
  • Ao calcular para RDD3, marque persistência
    insira a descrição da imagem aqui
  • Calcular o RDD4 é iniciar o cálculo com base nos dados armazenados em cache no RDD3, sem executá-lo do início ao fim
    insira a descrição da imagem aqui
  • Calcular o RDD5 é iniciar o cálculo com base nos dados armazenados em cache no RDD3, sem executá-lo do início ao fim
    insira a descrição da imagem aqui

Em segundo lugar, o nível de armazenamento

(1) Parâmetros do método de persistência

  • Use o método persist() do RDD para obter persistência e passe um StorageLevelobjeto para o método persist() para especificar o nível de armazenamento. Cada RDD persistente pode ser armazenado usando um nível de armazenamento diferente, o nível de armazenamento padrão é StorageLevel.MEMORY_ONLY.

(2) Tabela de nível de armazenamento Spark RDD

  • Existem sete níveis de armazenamento para Spark RDDs
    insira a descrição da imagem aqui
  • Na operação Shuffle do Spark (como reduceByKey()), alguns dados intermediários são salvos automaticamente mesmo que o usuário não use o método persist(). Isso é feito para evitar recalcular a entrada inteira se ela falhar durante o embaralhamento de nós. Se você quiser usar um RDD várias vezes, é altamente recomendável chamar persist()métodos nesse RDD.

(3) Como escolher o nível de armazenamento - compensação entre uso de memória e eficiência da CPU

  • Se o RDD for armazenado na memória sem estouro, o nível de armazenamento padrão (MEMORY_ONLY) é o preferido, o que maximiza o desempenho da CPU e permite que as operações no RDD sejam executadas na velocidade mais rápida.
  • Se o RDD transbordar quando armazenado na memória, use MEMORY_ONLY_SER e escolha uma biblioteca de serialização rápida para serializar o objeto para economizar espaço e ainda ser razoavelmente rápido para acessar.
  • A menos que calcular um RDD seja muito caro, ou que o RDD filtre muitos dados, não grave dados derramados no disco, porque recalcular partições pode ser tão rápido quanto lê-los do disco.
  • Se desejar uma recuperação rápida em caso de falha do servidor, você pode usar o nível de armazenamento de várias cópias MEMORY_ONLY_2 ou MEMORY_AND_DISK_2. Esse nível de armazenamento permite que as tarefas continuem em execução em RDDs após a perda de dados sem ter que esperar que as partições perdidas sejam recalculadas. Outros níveis de armazenamento exigem o recalculo de partições perdidas após a perda de dados.

(4) Visualize o código-fonte dos métodos persist() e cache()

/**                                                                                           
 * 在第一次行动操作时持久化RDD,并设置存储级别,当RDD从来没有设置过存储级别时才能使用该方法                                           
 */                                                                                          
def persist(newLevel: StorageLevel): this.type = {
    
                                                
  if (isLocallyCheckpointed) {
    
                                                                    
    // 如果之前已将该RDD设置为localCheckpoint,就覆盖之前的存储级别                                                
    persist(LocalRDDCheckpointData.transformStorageLevel(newLevel), allowOverride = true)     
  } else {
    
                                                                                        
    persist(newLevel, allowOverride = false)                                                  
  }                                                                                           
}                                                                                             
/**                                                                                           
  * 持久化RDD,使用默认存储级别(MEMORY_ONLY)                                                              
  */                                                                                          
def persist(): this.type = persist(StorageLevel.MEMORY_ONLY)                                  
                                                                                              
/**                                                                                           
  * 持久化RDD,使用默认存储级别(MEMORY_ONLY)                                                              
  */                                                                                          
def cache(): this.type = persist()                                                            
  • Como pode ser visto no código acima, o método cache() chama o método sem parâmetros do método persist(), e o nível de armazenamento padrão de ambos é MEMORY_ONLY, mas o método cache() não pode alterar o nível de armazenamento, enquanto persist () pode passar parâmetros de níveis de armazenamento personalizados.

(5) Demonstração de Caso Configurando o Nível de Armazenamento

  • net.huawei.rddCriar TestPersistobjetos em pacotes
    insira a descrição da imagem aqui
package net.huawei.rdd

import org.apache.log4j.{
    
    Level, Logger}
import org.apache.spark.{
    
    SparkConf, SparkContext}
import org.apache.spark.rdd.RDD

/**
  * 功能:演示持久化操作
  * 作者:华卫
  * 日期:2022年04月11日
  */
object TestPersist {
    
    
  def main(args: Array[String]): Unit = {
    
    
    // 创建Spark配置对象
    val conf = new SparkConf()
    conf.setAppName("TestPersist")
      .setMaster("local")
      .set("spark.testing.memory", "2147480000")
    // 基于配置创建Spark上下文
    val sc = new SparkContext(conf)

    // 去除Spark运行信息
    Logger.getLogger("org").setLevel(Level.OFF)
    Logger.getLogger("com").setLevel(Level.OFF)
    System.setProperty("spark.ui.showConsoleProgress", "false")
    Logger.getRootLogger().setLevel(Level.OFF)

    //创建RDD
    val rdd: RDD[Int] = sc.parallelize(List(100, 200, 300, 400, 500))

    //将RDD标记为持久化,默认存储级别为StorageLevel.MEMORY_ONLY
    rdd.persist()
    // rdd.persist(StorageLevel.DISK_ONLY)  //持久化到磁盘
    // rdd.persist(StorageLevel.MEMORY_AND_DISK)//持久化到内存,将溢出的数据持久化到磁盘

    // 第一次行动算子计算时,将对标记为持久化的RDD进行持久化操作
    val result: String = rdd.collect().mkString(", ")
    println(result)

    // 第二次行动算子计算时,将直接从持久化的目的地读取数据进行操作,而不需要从头计算数据
    rdd.collect().foreach(println)
  }
}
  • Execute o programa e veja os resultados
    insira a descrição da imagem aqui

3. Use o Spark WebUI para visualizar o cache

(1) Crie um RDD e marque-o para persistência

insira a descrição da imagem aqui

(2) Spark WebUI para visualizar informações de armazenamento RDD

  • Acesse a WebUI do Spark Shell no navegador para http://master:4040/storage/visualizar as informações de armazenamento RDD e você pode ver que as informações de armazenamento estão vazias
    insira a descrição da imagem aqui
  • Execute o comando: rdd.collect(), colete dados RDD
    insira a descrição da imagem aqui
  • Atualize a WebUI e descubra que há uma ParallelCollectionRDDinformação de armazenamento, o nível de armazenamento do RDD é MEMORY, a partição persistente é 8, e ela está completamente armazenada na memória.
    insira a descrição da imagem aqui
  • Clique ParallelCollectionRDDno hiperlink para visualizar as informações detalhadas de armazenamento do RDD
    insira a descrição da imagem aqui
  • A operação acima mostra que chamar o método persist() de um RDD apenas marca o RDD como persistente, e o RDD marcado como persistente só será persistido quando uma operação de ação for executada.
  • Execute os seguintes comandos para criar rdd2 e persistir rdd2 no disco
    insira a descrição da imagem aqui
  • Atualize a WebUI acima e encontre mais uma MapPartitionsRDDinformação de armazenamento.O nível de armazenamento do RDD é DISK, a partição persistente é 8, e está completamente armazenada no disco.
    insira a descrição da imagem aqui

(3) Exclua o RDD do cache

  • Execute o seguinte comando, ele será removido rdd(ParallelCollectionRDD)do cache
    insira a descrição da imagem aqui
  • Atualize a WebUI acima e descubra que resta apenas uma MapPartitionsRDD, que ParallelCollectionRDDfoi removida.
    insira a descrição da imagem aqui
  • O Spark monitora automaticamente o uso do cache em cada nó e remove os dados de partição antigos do cache da maneira menos usada recentemente. Se você deseja excluir um RDD manualmente, em vez de esperar que o RDD seja excluído automaticamente do cache pelo Spark, você pode usar o unpersist()método RDD.

Acho que você gosta

Origin blog.csdn.net/howard2005/article/details/124092714
Recomendado
Clasificación