当前位置 博文首页 > Shockang的博客:Spark的临时数据不自动清理
本文隶属于专栏《Spark异常问题汇总》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!
本专栏目录结构和参考文献请见 Spark异常问题汇总
在处理 Spark 任务时,会使用到 SparkClient 来提交任务。
默认会在 Linux 的 /tmp 目录下产生大量的临时目录(包含有文件)。
正常的运行流程是在执行完任务后,会删除产生的这类临时目录,但是有时会发现这类临时目录却无法自动删除。
这里直接翻阅 Spark 的源代码,发现任务在运行过程中产生的临时目录是由 Util.scala 类来创建的。
该类在 Spark 的 spark/core/src/main/scala/org/apache/spark/util/Utils.scala 中。
/**
* Create a temporary directory inside the given parent directory. The directory will be
* automatically deleted when the VM shuts down.
*/
def createTempDir(
root: String = System.getProperty("java.io.tmpdir"),
namePrefix: String = "spark"): File = {
val dir = createDirectory(root, namePrefix)
ShutdownHookManager.registerShutdownDeleteDir(dir)
dir
}
利用 Java 虚拟机读取 java.io.tmpdir 属性获取系统的 tmp 目录路径,然后在该目录下创建 Spark 任务产生的临时数据。
执行删除操作的类在 spark/core/src/main/scala/org/apache/spark/util/ShutdownHookManager.scala 目录下,通过 ShutdownHookManager 类来管理临时目录中的数据何时自动删除。
// Add a shutdown hook to delete the temp dirs when the JVM exits
logDebug("Adding shutdown hook") // force eager creation of logger
addShutdownHook(TEMP_DIR_SHUTDOWN_PRIORITY) { () =>
logInfo("Shutdown hook called")
// we need to materialize the paths to delete because deleteRecursively removes items from
// shutdownDeletePaths as we are traversing through it.
shutdownDeletePaths.toArray.foreach { dirPath =>
try {
logInfo("Deleting directory " + dirPath)
Utils.deleteRecursively(new File(dirPath))
} catch {
case e: Exception => logError(s"Exception while deleting Spark temp dir: $dirPath", e)
}
}
}
这里使用的是 jvm 的 ShutdownHook ,如果 Driver 进程一直处于运行状态,自然这个 Hook 就无法触发。
从而产生的临时文件就无法自动被删除。
另外,如果 Spark 任务处于运行状态,如果使用 Linux 的 kill -9 命令强制停止,则 jvm 中的 Hook 无法触发自动清理临时目录的操作,导致 Spark 任务在运行过程中产生的临时数据会保留在 tmp 目录中。
提示:只有在 JVM 执行完任务正常退出后,才会触发自动清理临时目录的操作。
面对临时数据不自动清理的情况,可以通过以下方式来解决这个异常问题。
制定规范的操作流程,告知用户在提交、管理 Spark 任务的时候,需要按照制定的规范进行操作。
编写 Linux 脚本,使用 Crontab 来定时调度执行脚本命令,让其周期性地清理 Spark 任务产生的临时目录和数据。
cs