我正在尝试根据列表中这些对象的字段过滤RDD中的对象集合。
我尝试的方法与此处相同: Filter based on another RDD in Spark
val namesToFilterOn = sc.textFile("/names_to_filter_on.txt").collect.toSet
val usersRDD = userContext.loadUsers("/user.parquet")
这有效:
usersRDD.filter(user => Set("Pete","John" ).contains( user.firstName )).first
当我尝试
时usersRDD.filter(user => namesToFilterOn.contains( user.firstName )).first
我收到此错误
org.apache.spark.SparkException: Task not serializable
Caused by: java.io.NotSerializableException: org.apache.spark.SparkContext
我尝试这个时遇到同样的错误
val shortTestList = Set("Pete","John" )
usersRDD.filter(user => shortTestList .contains( user.firstName )).first
为什么在这些过滤器语句中指定一组名称/字符串时会出现这个错误?
据我所知,这应该可行,我没有在filter语句中的任何地方指定SparkContext。那么为什么会出错呢?怎么不得到错误?
我使用的Spark版本是1.5.2。
我还尝试先播放一组名字。
val namesToFilterOnBC = sc.broadcast(namesToFilterOn)
usersRDD.filter(user => namesToFilterOnBC.value.contains( user.firstName )).first
这又导致同样的错误
org.apache.spark.SparkException: Task not serializable
Caused by: java.io.NotSerializableException: org.apache.spark.SparkContext
答案 0 :(得分:1)
原因是val namesToFilterOn = sc.textFile("/names_to_filter_on.txt").collect.toSet
属于包含不可序列化的val并因此包含错误的对象。
当user => namesToFilterOn.contains( user.firstName )
转换为字节格式以通过线路发送给执行程序时,Spark会检查是否存在对不可序列化对象的引用,并且SparkContext就在其中。
Spark似乎找到了一个引用非序列化SparkContext的地方并抛出了异常。
解决方案是将val namesToFilterOn = sc.textFile("/names_to_filter_on.txt").collect.toSet
或val shortTestList = Set("Pete","John" )
包装为Scala中object
的单独方法。您还可以在闭包内使用其他val shortTestList
(如Job aborted due to stage failure: Task not serializable中所述)或broadcast。
您可能会发现文档SIP-21 - Spores非常适合该案例。
答案 1 :(得分:0)
询问userContext的开发人员并通过不显式实例化userContext而只是导入其函数来解决问题。
import userContext._
sc.loadUsers("/user.parquet")
usersRDD.filter(user => namesToFilterOn.contains( user.firstName )).first
而不是
val userContext = new UserContext(sc)
userContext.loadUsers("/user.parquet")
usersRDD.filter(user => namesToFilterOn.contains( user.firstName )).first