Spark:任务不可序列化(Broadcast / RDD / SparkContext)

时间:2015-08-28 09:59:58

标签: scala serialization apache-spark yarn

Spark中有很多关于Task is not serializable的问题。但是,这种情况似乎很特别。

我创建了一个类:

class Neighbours(e: RDD[E], m: KMeansModel) extends Serializable {
  val allEs: RDD[(String, E)] = e.map(e => (e.w, e))
    .persist()
  val sc = allEs.sparkContext
  val centroids = sc.broadcast(m.clusterCenters)
  [...]

该类定义了以下方法:

private def centroidDistances(v: Vector): Array[Double] = {
  centroids.value.map(c => (centroids.value.indexOf(c), Vectors.sqdist(v, c)))
    .sortBy(_._1)
    .map(_._2)
}

但是,调用该类时,会抛出Task is not serializable异常。

奇怪的是,类Neighbours的标题中的微小变化足以解决问题。我没有创建用于广播的val sc: SparkContext,而只是内联创建Spark上下文的代码:

class Neighbours(e: RDD[E], m: KMeansModel) extends Serializable {
  val allEs: RDD[(String, E)] = e.map(e => (e.w, e))
  .setName("embeddings")
  .persist()
  val centroids = allEmbeddings.sparkContext(m.clusterCenters)
  [...]

我的问题是:第二种变体如何产生影响?第一个出了什么问题?直觉上,这应该只是语法糖,这是Spark中的一个错误吗?

我在Hadoop / Yarn集群上使用Spark 1.4.1。

1 个答案:

答案 0 :(得分:1)

定义时

class Neighbours(e: RDD[E], m: KMeansModel) extends Serializable {
  ...
  val sc = allEmbeddings.sparkContext
  val centroids = sc.broadcast(m.clusterCenters)
  ...
}

您已将sc转换为类变量,这意味着可以从Neighbours的实例访问它。 neighbours.sc。这意味着sc需要可序列化,但事实并非如此。

在内联代码时,只需要centroids的最终值可序列化。 centroids的类型为Broadcast,可序列化。