给定以下案例类别:
case class User(name:String, age:Int)
从用户实例的List
创建RDD
以下代码过滤RDD以删除50岁以上的用户
trait Process {
def test {
val rdd = ... // create RDD
rdd.filter(_.age>50)
}
}
为了添加日志记录,创建了一个单独的验证函数并将其传递给过滤器,如下所示:
trait Process {
def validate(user:User) {
if (user.age>50) {
true
}
else {
println("FAILED VALIDATION")
false
}
}
def test {
val rdd = ... // create RDD
rdd.filter(validate)
}
}
引发以下异常:
org.apache.spark.SparkException: Task not serializable
代码的工作原理是使定义验证函数的类可序列化:
trait Process extends Serializable
这是处理Task not serializable
异常的正确方法吗?还是在Spark中使用序列化会降低性能?有更好的方法吗?
感谢
在Spark 中使用序列化会降低性能吗
任务序列化(与混洗/收集数据时发生的数据串行化相反)在性能方面很少引人注目,只要序列化的对象很小。每个任务序列化一次(与处理的数据量无关)。
在这种情况下(序列化Process
实例),性能影响可能可以忽略不计,因为它是一个小对象。
这种假设("Process
很小,所以没关系")的风险在于,随着时间的推移,Process
可能会发生变化:开发人员很容易不会注意到这个类被序列化了,所以他们可能会添加一些成员,从而使其变慢。
有没有更好的方法来做这个
通过使用静态方法(objects
的方法,而不是类),可以完全避免序列化。在这种情况下,您可以为Process
:创建伴随对象
import Process._
trait Process {
def test {
val rdd = ... // create RDD
rdd.filter(validate)
}
}
object Process {
def validate(user:User) {
if (user.age>50) {
true
} else {
println("FAILED VALIDATION")
false
}
}
对象是"静态"的,因此Spark可以在不序列化的情况下使用它们。