org.apache.spark.SparkException:任务不可序列化 - 使用参数时

时间:2015-04-11 18:32:19

标签: apache-spark rdd

尝试在Task not serializable中使用输入参数时出现map错误:

val errors = inputRDD.map { 
    case (itemid, itemVector, userid, userVector, rating) =>
    (itemid, itemVector, userid, userVector, rating, 
        (
            (rating - userVector.dot(itemVector)) * itemVector) 
            - h4 * userVector
        )
    }

我将h4传递给了Class的参数。

map是一种方法,如果在我提出map转换之前它可以正常工作:

val h4 = h4

如果我不这样做,或者把它放在方法之外,那么它就不起作用,我得到Task not serialisable。为什么会这样?我为方法中的方法工作之外的类生成的其他val,那么如何从输入参数/参数实例化val呢?

2 个答案:

答案 0 :(得分:2)

该错误表示h4所属的类不是Serializable。

以下是一个类似的例子:

class ABC(h: Int) { 
  def test(s:SparkContext) = s.parallelize(0 to 5).filter(_ > h).collect 
}

new ABC(3).test(sc)
//org.apache.spark.SparkException: Job aborted due to stage failure: 
//    Task not serializable: java.io.NotSerializableException: 
//    $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$ABC

在rdd转换中使用this.h时,this将成为序列化的闭包的一部分。

使Serializable类按预期工作:

class ABC(h: Int) extends Serializable { 
  def test(s:SparkContext) = s.parallelize(0 to 5).filter(_ > h).collect
}

new ABC(3).test(sc)
// Array[Int] = Array(4, 5)

通过在方法中定义局部变量,删除对rdd转换中this的引用也是如此:

class ABC(h: Int) { 
  def test(s:SparkContext) = { 
      val x = h;
      s.parallelize(0 to 5).filter(_ > x).collect 
  }
}

new ABC(3).test(sc)
// Array[Int] = Array(4, 5)

答案 1 :(得分:0)

您可以使用广播变量。它的广播数据从你的变量到你的所有工人。有关详细信息,请访问此link