Scala Spark函数不可序列化
我有一门课:Scala Spark函数不可序列化,scala,apache-spark,Scala,Apache Spark,我有一门课: class DataLoader { def rdd2RddTransform( ss: SparkSession, inputRDD: RDD[GenericRecord]): RDD[GenericRecord] = { inputRDD.asInstanceOf[RDD[TrainingData]] .map(reformatTrainingData) } private def reformatTrainin
class DataLoader {
def rdd2RddTransform(
ss: SparkSession,
inputRDD: RDD[GenericRecord]): RDD[GenericRecord] = {
inputRDD.asInstanceOf[RDD[TrainingData]]
.map(reformatTrainingData)
}
private def reformatTrainingData: TrainingData => ReFormatedData
= (trainingData: TrainingData) => {func implement}
}
它工作得很好,但引发了一个异常:
org.apache.spark.SparkException:任务不可序列化
在我对RDD的映射做了一个小更改之后:
inputRDD.asInstanceOf[RDD[TrainingData]].map(reformatTrainingData(_))
我认为这两个功能应该是相同的,但似乎不是。为什么它们不同?这是因为方法和函数在Scala中不太可互换 函数是独立的对象(即类的实例,如
Function1
、Function2
、Function3
…),但方法仍然与其封闭类绑定。如果封闭类不可序列化,这可能会在Spark中产生问题-当Spark尝试序列化方法时,它无法序列化关联的类实例
请注意,reformatTrainingData
是一个返回函数的方法
所以当你打电话时,比如:
rdd.map(reformatTrainingData)
实际上,您正在调用no-argreformatTrainingData
方法,并返回一个可以安全序列化的独立Function1
实例。你也可以这样写
private def reformatTrainingData(): TrainingData => ReFormatedData ...
rdd.map(reformatTrainingData())
强调有一个方法调用正在发生
当您更改为reformatTrainingData(41;
时,您使用的是部分应用的方法;当Spark尝试对此进行序列化时,它需要拉入并序列化封闭的数据加载器
类,该类未标记为可序列化
如果reformatTrainingData
是类型为TrainingData=>ReFormatedData
的简单方法,则会出现相同的问题
如果将DataLoader
标记为extends Serializable
,则两个版本都可以工作
将reformatTrainingData
转换为val
也可以,因为val在序列化时不会拉入封闭类:
private val reformatTrainingData: TrainingData => ReFormatedData ...
rdd.map(reformatTrainingData)
我怀疑这是由于Scala中函数和方法之间的差异造成的。能否发布堆栈跟踪中包含序列化调试信息的部分?请参阅以获取示例