Scala Spark缓存的RDD计算n次

Scala Spark缓存的RDD计算n次,scala,performance,apache-spark,yarn,Scala,Performance,Apache Spark,Yarn,我面临一个Spark应用程序的问题。以下是我的代码的简化版本: def main(args: Array[String]) { // Initializing spark context val sc = new SparkContext() val nbExecutors = sc.getConf.getInt("spark.executor.instances", 3) System.setProperty("spark.sql.shuffle.partiti

我面临一个Spark应用程序的问题。以下是我的代码的简化版本:

def main(args: Array[String]) {
    // Initializing spark context
    val sc = new SparkContext()
    val nbExecutors = sc.getConf.getInt("spark.executor.instances", 3)
    System.setProperty("spark.sql.shuffle.partitions", nbExecutors.toString)

    // Getting files from TGZ archives
    val archivesRDD: RDD[(String,PortableDataStream)] = utils.getFilesFromHDFSDirectory("/my/dir/*.tar.gz") // This returns an RDD of tuples containing (filename, inpustream)
    val filesRDD: RDD[String] = archivesRDD.flatMap(tgzStream => {
        logger.debug("Getting files from archive : "+tgzStream._1)
        utils.getFilesFromTgzStream(tgzStream._2)
    })

    // We run the same process with 3 different "modes"
    val modes = Seq("mode1", "mode2", "mode3")

    // We cache the RDD before
    val nb = filesRDD.cache().count()
    logger.debug($nb + " files as input")

    modes.map(mode => {
        logger.debug("Processing files with mode : " + mode)
        myProcessor.process(mode, filesRDD)
    })

    filesRDD.unpersist() // I tried with or without this

    [...]
}
生成的日志包括(例如,输入3个存档):

从存档中获取文件:一个

从存档中获取文件:b

从存档中获取文件:c

3个文件作为输入

使用模式处理文件:mode1

从存档中获取文件:一个

从存档中获取文件:b

从存档中获取文件:c

使用模式处理文件:mode2

从存档中获取文件:一个

从存档中获取文件:b

从存档中获取文件:c

使用模式处理文件:mode3

从存档中获取文件:一个

从存档中获取文件:b

从存档中获取文件:c

我的Spark配置:

  • 版本:1.6.2
  • 执行器:20 x 2CPU x 8Go RAM
  • 每个执行器的纱线开销内存:800Mo
  • 驱动器:1CPU x 8Go RAM
我从这些日志中了解到,文件提取执行了4次,而不是一次读取!这显然会导致堆空间问题和性能泄漏

我做错什么了吗


编辑:我也尝试使用
模式。foreach(…)
而不是map,但没有任何更改…

您是否尝试将
模式。map
结果传递到列表构造函数中(即
列表(modes.map{/*…*/})
?有时(我不确定什么时候)Scala集合会延迟计算映射,因此,如果在spark删除缓存后才对这些映射进行计算,则必须重新计算。

好的,经过大量测试,我终于解决了这个问题。事实上有两个问题:

  • 我低估了输入数据的大小:Spark的
    cache
    persist
    函数是无效的如果RDD太大,无法完全存储在总内存的60%中,我知道这一点,但我认为我的输入数据没有那么大,但实际上我的RDD是80GB。但是我60%的内存(160GB)仍然超过80GB,所以发生了什么?问题2的答案

  • 我的分区太大:在我的代码中,我的RDD的分区数被设置为100,所以我有100个分区,每个分区的容量为1.6GB。问题是,我的数据是由字符串组成的,每个字符串由几十个MEG组成,因此我的分区没有满,10GB的已用内存实际上只包含7或8GB的真实数据


  • 为了解决这些问题,我不得不使用
    persist(StorageLevel.MEMORY\u SER)
    ,这增加了计算时间,但大大减少了内存使用()并将分区数设置为1000(根据Spark文档,该文档建议分区为~128MB)

    也许你应该尝试直接缓存你定义的
    文件rdd
    @astro\u asz。我不确定你的意思。谢谢,但是这个修复程序仍然不能正常工作