是什么导致排序功能可在Spark中序列化?

时间:2016-10-05 14:43:07

标签: scala apache-spark

我正在为下面的代码获取不可序列化的任务。 但是,如果我直接传递函数,我不会收到任何错误。

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)

导致错误的原因是什么?

2 个答案:

答案 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))
}