我知道这个问题已被多次回答,但我尝试了一切,但我没有找到解决方案。我有以下代码引发NotSerializableException
val ids : Seq[Long] = ...
ids.foreach{ id =>
sc.sequenceFile("file", classOf[LongWritable], classOf[MyWritable]).lookup(new LongWritable(id))
}
出现以下异常
Caused by: java.io.NotSerializableException: org.apache.hadoop.io.LongWritable
Serialization stack:
...
org.apache.spark.serializer.JavaSerializationStream.writeObject(JavaSerializer.scala:47)
at org.apache.spark.serializer.JavaSerializerInstance.serialize(JavaSerializer.scala:84)
at org.apache.spark.util.ClosureCleaner$.ensureSerializable(ClosureCleaner.scala:301)
创建SparkContext时,我做
val sparkConfig = new SparkConf().setAppName("...").setMaster("...")
sparkConfig.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
sparkConfig.registerKryoClasses(Array(classOf[BitString[_]], classOf[MinimalBitString], classOf[org.apache.hadoop.io.LongWritable]))
sparkConfig.set("spark.kryoserializer.classesToRegister", "org.apache.hadoop.io.LongWritable,org.apache.hadoop.io.Text,org.apache.hadoop.io.LongWritable")
并查看环境选项卡,我可以看到这些条目。但是,我不明白为什么
我正在使用Apache Spark v.1.5.1
答案 0 :(得分:4)
在循环内重复加载相同的数据是非常低效的。如果针对相同的数据执行操作,请加载一次并缓存:
val rdd = sc
.sequenceFile("file", classOf[LongWritable], classOf[MyWritable])
rdd.cache()
Spark并不认为Hadoop Writable可序列化。这是一个开放的JIRA(SPARK-2421)。要处理LongWritables
简单get
应该足够:
rdd.map{case (k, v) => k.get()}
关于您的自定义类,您有责任解决此问题。
有效查找需要分区RDD。否则,它必须搜索RDD中的每个分区。
import org.apache.spark.HashPartitioner
val numPartitions: Int = ???
val partitioned = rdd.partitionBy(new HashPartitioner(numPartitions))
一般来说,RDD不是为随机访问而设计的。即使定义了分区器lookup
也必须线性搜索候选分区。在RDD中使用5000个均匀分布的密钥和10M对象,这很可能意味着在整个RDD上重复搜索。您可以选择避免这种情况:
过滤器
val idsSet = sc.broadcast(ids.toSet)
rdd.filter{case (k, v) => idsSet.value.contains(k)}
加入
val idsRdd = sc.parallelize(ids).map((_, null))
idsRdd.join(rdd).map{case (k, (_, v)) => (k, v)}
IndexedRDD
- 它并不像一个特别活跃的项目
使用10M条目,您在本地搜索内存可能比使用Spark更好。对于较大的数据,您应该考虑使用正确的键值存储。
答案 1 :(得分:0)
我是apache spark的新手,但是试图解决你的问题,请评估它,如果它可以帮助你解决序列化的问题,它会发生因为spark-hadoop LongWritable和其他可写的问题没有序列化。
val temp_rdd = sc.parallelize(ids.map(id =>
sc.sequenceFile("file", classOf[LongWritable], classOf[LongWritable]).toArray.toSeq
)).flatMap(identity)
ids.foreach(id =>temp_rdd.lookup(new LongWritable(id)))