case class MovieRaw(movieid:Long,genres:String,title:String)
case class Movie(movieid:Long,genres:Set[String],title:String,year:Int)
val regexYear = ".*\\((\\d*)\\)".r
moviesRaw.map{case MovieRaw(i,g,t) => Movie(i,g,t,t.trim() match { case regexYear(y) => Integer.parseInt(y)})}
执行最后一个命令时,我收到以下错误:
java.io.NotSerializableException: org.apache.spark.SparkConf
使用此SparkContext在Spark / Scala REPL中运行:
val conf = new SparkConf(true).set("spark.cassandra.connection.host", "localhost")
val sc = new SparkContext(conf)
答案 0 :(得分:2)
正如Dean解释的那样,问题的原因是REPL在添加到REPL的代码中创建了一个类,在这种情况下,同一个上下文中的其他变量在闭包中被“拉”。正则表达式声明。
鉴于您创建上下文的方式,避免该序列化问题的一种简单方法是声明SparkConf
和SparkContext
瞬态:
@transient val conf = new SparkConf(true).set("spark.cassandra.connection.host", "localhost")
@transient val sc = new SparkContext(conf)
您甚至不需要在REPL中重新创建spark上下文,仅用于连接到Cassandra:
spark-shell --conf spark.cassandra.connection.host=localhost
答案 1 :(得分:1)
您可能在更大的Scala类或对象(类型)中拥有此代码,对吧?如果是这样,为了序列化regexYear
,整个封闭类型会被序列化,但您可能在该类型中定义了SparkConf
。
这是一个非常常见和令人困惑的问题,并且正在努力防止它,考虑到JVM和Java之类的语言的限制,如Java。
解决方案(暂时)是将regexYear
放在方法或其他对象中:
object MyJob {
def main(...) = {
case class MovieRaw(movieid:Long,genres:String,title:String)
case class Movie(movieid:Long,genres:Set[String],title:String,year:Int)
val regexYear = ".*\\((\\d*)\\)".r
moviesRaw.map{case MovieRaw(i,g,t) => Movie(i,g,t,t.trim() match { case regexYear(y) => Integer.parseInt(y)})}
...
}
}
或
...
object small {
case class MovieRaw(movieid:Long,genres:String,title:String)
case class Movie(movieid:Long,genres:Set[String],title:String,year:Int)
val regexYear = ".*\\((\\d*)\\)".r
moviesRaw.map{case MovieRaw(i,g,t) => Movie(i,g,t,t.trim() match { case regexYear(y) => Integer.parseInt(y)})}
}
希望这有帮助。
答案 2 :(得分:1)
尝试在命令行上传入cassandra选项,如下所示:
spark-shell [other options] --conf spark.cassandra.connection.host=localhost
这样你就不必重新创建SparkContext - 你可以使用SparkContext(sc)自动用spark-shell实例化。