我正在为下面的代码获取不可序列化的任务。 但是,如果我直接传递函数,我不会收到任何错误。
abstract class MyAbstractClass[T, SortOrder](implicit ord: Ordering[SortOrder]) {
def getSorterFunc(): (T) => SortOrder
def sort(rdd: RDD[List[T]]) = {
val sortFunc = getSorterFunc()
rdd.map(x => x.sortBy(sortFunc))
}
}
object SampleObject extends MyAbstractClass[(String, Int, List[Int]), (String, Int)] {
def getSorterFunc() = {
case (username, id, addresses) => (username, id)
}
}
val data = Array(("user1",1,List(12,211)),("u2",1,List(12,211)),("u1",2,List(12,211))).toList
val dataList = Array(data,data)
val rdd = sc.parallelize(dataList)
// This is working fine
rdd.map(x => x.sortBy{ case (username, id, addresses) => (username, id) })
// This is giving task not serializable error.
SampleObject.sort(rdd)
rdd.collect
错误:
org.apache.spark.SparkException: Task not serializable
at org.apache.spark.util.ClosureCleaner$.ensureSerializable(ClosureCleaner.scala:304)
at org.apache.spark.util.ClosureCleaner$.org$apache$spark$util$ClosureCleaner$$clean(ClosureCleaner.scala:294)
at org.apache.spark.util.ClosureCleaner$.clean(ClosureCleaner.scala:122)
at org.apache.spark.SparkContext.clean(SparkContext.scala:2055)
at org.apache.spark.rdd.RDD$$anonfun$map$1.apply(RDD.scala:324)
at org.apache.spark.rdd.RDD$$anonfun$map$1.apply(RDD.scala:323)
at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:150)
at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:111)
at org.apache.spark.rdd.RDD.withScope(RDD.scala:316)
导致错误的原因是什么?
答案 0 :(得分:3)
这里的罪魁祸首是implicit ord: Ordering[SortOrder]
- 因为sort
方法(在一个必须由Spark序列化的匿名函数中调用)隐式地将ord
作为参数,封装对象{{ 1}}必须是可序列化的。
这就是为什么使用局部变量SampleObject
是不够的 - 实际上这使得Spark无需序列化调用sortFunc
的对象,但仍然需要getSorterFunc
照顾。
正如评论中所述,您可以通过ord
(或SampleObject
)扩展MyAbstractClass
来解决此问题。
另一种选择是从类中移动隐式参数(这使得它成为一个成员,这意味着它在序列化时“将类与其一起携带”到方法< / EM>:
Seriablizable
无需序列化该类即可。
答案 1 :(得分:1)
看起来有一个非常简单的解决方案(基于Tzach Zohar的调查结果):
...
def sort(rdd: RDD[List[T]]) = {
val sortFunc = getSorterFunc()
val ordLocal = ord
rdd.map(x => x.sortBy(sortFunc)(ordLocal))
}