我有一个大小为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上)。
任何提示或建议都值得赞赏。