当前位置 博文首页 > Shockang的博客:Spark的临时数据不自动清理

    Shockang的博客:Spark的临时数据不自动清理

    作者:[db:作者] 时间:2021-08-13 09:48

    前言

    本文隶属于专栏《Spark异常问题汇总》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

    本专栏目录结构和参考文献请见 Spark异常问题汇总

    正文

    在处理 Spark 任务时,会使用到 SparkClient 来提交任务。
    默认会在 Linux 的 /tmp 目录下产生大量的临时目录(包含有文件)。
    正常的运行流程是在执行完任务后,会删除产生的这类临时目录,但是有时会发现这类临时目录却无法自动删除。

    1 .分析源代码

    这里直接翻阅 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 执行完任务正常退出后,才会触发自动清理临时目录的操作。

    2 .解决方式

    面对临时数据不自动清理的情况,可以通过以下方式来解决这个异常问题。

    规范使用

    制定规范的操作流程,告知用户在提交、管理 Spark 任务的时候,需要按照制定的规范进行操作。

    配置脚本清理

    编写 Linux 脚本,使用 Crontab 来定时调度执行脚本命令,让其周期性地清理 Spark 任务产生的临时目录和数据。

    cs