Spark 和不可序列化的 DateTimeFormatter

Posted

技术标签:

【中文标题】Spark 和不可序列化的 DateTimeFormatter【英文标题】:Spark and Not Serializable DateTimeFormatter 【发布时间】:2016-07-08 01:05:08 【问题描述】:

我正在尝试在 Spark 中使用 java.time.format 中的 DateTimeFormatter,但它似乎不可序列化。这是相关的代码块:

val pattern = "<some pattern>".r
val dtFormatter = DateTimeFormatter.ofPattern("<some non-ISO pattern>")

val logs = sc.wholeTextFiles(path)

val entries = logs.flatMap(fileContent => 
    val file = fileContent._1
    val content = fileContent._2
    content.split("\\r?\\n").map(line => line match 
      case pattern(dt, ev, seq) => Some(LogEntry(LocalDateTime.parse(dt, dtFormatter), ev, seq.toInt))
      case _ => logger.error(s"Cannot parse $file: $line"); None
    )
  )

如何避免java.io.NotSerializableException: java.time.format.DateTimeFormatter 异常?是否有更好的库来解析时间戳?我读到 Joda 也不是可序列化的,并且已合并到 Java 8 的时间库中。

【问题讨论】:

【参考方案1】:

您可以通过两种方式避免序列化:

    假设它的值可以是常数,将格式化程序放在object 中(使其成为“静态”)。这意味着静态值可以在每个工作人员中访问,而不是驱动程序将其序列化并发送给工作人员:

    object MyUtils 
      val dtFormatter = DateTimeFormatter.ofPattern("<some non-ISO pattern>")
    
    
    import MyUtils._
    logs.flatMap(fileContent => 
      // can safely use formatter here
    )
    

    在匿名函数中按记录实例化它。这会带来一些性能损失(因为实例化会一遍又一遍地发生,每条记录),所以只有在第一个无法应用时才使用此选项:

    logs.flatMap(fileContent => 
      val dtFormatter = DateTimeFormatter.ofPattern("<some non-ISO pattern>")
      // use formatter here
    )
    

【讨论】:

【参考方案2】:

另一种方法是使 DateTimeFormatter 瞬态。这告诉 JVM/Spark 变量不会被序列化,而是从头开始构造。对于每个执行器构建成本低的东西,例如 DateTimeFormatter,这是一个很好的方法。

这里是an article that describes this in more detail。

【讨论】:

大小姐这个序列化方面/问题。

以上是关于Spark 和不可序列化的 DateTimeFormatter的主要内容,如果未能解决你的问题,请参考以下文章

Spark Scala:任务不可序列化错误

Spark 应用程序收到“任务不可序列化”的错误?

在 Spark Scala 中使用自定义数据框类时任务不可序列化

Spark:DataFrame 上 UDF 的任务不可序列化

任务不可序列化错误:Spark

Spark:对象不可序列化