有没有一种更好的方法可以在Spark中加载巨大的tar文件,同时避免OutOfMemoryError?

时间:2018-11-09 22:56:24

标签: apache-spark tar

我有一个大小为40 GB的tar文件mytar.tar。在tar文件中有500个tar.gz文件,在这些tar.gz文件中的每个文件中都是一堆JSON文件。我已经编写了处理该tar文件的代码,并尝试获取JSON字符串内容的列表。我的代码如下所示。

val isRdd = sc.binaryFiles("/mnt/mytar.tar")
  .flatMap(t => { 
    val buf = scala.collection.mutable.ListBuffer.empty[TarArchiveInputStream]
    val stream = t._2
    val is = new TarArchiveInputStream(stream.open())
    var entry = is.getNextTarEntry()
    while (entry != null) {
      val name = entry.getName()
      val size = entry.getSize.toInt

      if (entry.isFile() && size > -1) {
        val content = new Array[Byte](size)
        is.read(content, 0, content.length)

        val tgIs = new TarArchiveInputStream(new GzipCompressorInputStream(new ByteArrayInputStream(content)))
        buf += tgIs
      }
      entry = is.getNextTarEntry()
    }
    buf.toList
  })
  .cache

val byteRdd = isRdd.flatMap(is => {
    val buf = scala.collection.mutable.ListBuffer.empty[Array[Byte]]
    var entry = is.getNextTarEntry()
    while (entry != null) {
      val name = entry.getName()
      val size = entry.getSize.toInt

      if (entry.isFile() && name.endsWith(".json") && size > -1) {
        val data = new Array[Byte](size)
        is.read(data, 0, data.length)
        buf += data
      }
      entry = is.getNextTarEntry()
    }
    buf.toList
  })
  .cache

val jsonRdd = byteRdd
  .map(arr => getJson(arr))
  .filter(_.length > 0)
  .cache

jsonRdd.count //action just to execute the code

执行此代码时,出现OutOfMemoryError(OOME)。

org.apache.spark.SparkException: Job aborted due to stage failure: 
Task 0 in stage 24.0 failed 4 times, most recent failure: 
Lost task 0.3 in stage 24.0 (TID 137, 10.162.224.171, executor 13): 
java.lang.OutOfMemoryError: Java heap space

我的EC2群集具有1个驱动程序和2个i3.xlarge类型的工作节点(30.5 GB内存,4个内核)。通过查看日志并进行思考,我相信OOME是在创建isRDD(输入流RDD)的过程中发生的。

在代码或Spark集群的创建中,我还有其他方法可以缓解此问题吗?我是否应该选择具有更多内存的EC2实例(例如,像R5.2xlarge这样的内存优化实例)? FWIW,我升级到R5.2xlarge群集设置,但仍然看到OOME。

我考虑过要做的一件事是解压缩mytar.tar,而是从内部的.tar.gz文件开始。我认为.tar.gz文件中的每个tar都必须小于30 GB,以避免OOME(在i3.xlarge上)。

任何提示或建议都值得赞赏。

0 个答案:

没有答案