Apache spark 序列化是否会降低Spark性能?

Apache spark 序列化是否会降低Spark性能?,apache-spark,Apache Spark,鉴于以下案例类别: case class User(name:String, age:Int) 从用户实例的列表创建RDD 下面的代码过滤RDD以删除50岁以上的用户 trait Process { def test { val rdd = ... // create RDD rdd.filter(_.age>50) } } 为了添加日志记录,将创建一个单独的验证函数并将其传递给过滤器,如下所示: trait Process { def validate(u

鉴于以下案例类别:

case class User(name:String, age:Int)
从用户实例的
列表创建
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
这是处理
任务不可序列化
异常的正确方法,还是在Spark中使用序列化会降低性能?有没有更好的方法

谢谢

在Spark中使用序列化是否会降低性能

只要序列化的对象很小,任务序列化(与数据序列化相反,数据序列化是在无序移动/收集数据时发生的)在性能方面很少值得注意。每个任务执行一次任务序列化(无论处理的数据量如何)

在这种情况下(序列化
进程
实例),性能影响可能可以忽略,因为它是一个小对象

这个假设的风险(
Process
很小,所以没关系)是随着时间的推移,
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可以在不序列化的情况下使用它们

在Spark中使用序列化是否会降低性能

只要序列化的对象很小,任务序列化(与数据序列化相反,数据序列化是在无序移动/收集数据时发生的)在性能方面很少值得注意。每个任务执行一次任务序列化(无论处理的数据量如何)

在这种情况下(序列化
进程
实例),性能影响可能可以忽略,因为它是一个小对象

这个假设的风险(
Process
很小,所以没关系)是随着时间的推移,
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可以在不序列化的情况下使用它们。

Tzach,谢谢。对于定义工作流和构成工作流的函数,是否最好完全避免类而只使用对象?我认为这是一种相当常见的做法-使用匿名函数或对象函数作为RDD转换。Tzach,谢谢。对于定义工作流和构成工作流的函数,是否最好完全避免类而只使用对象?我认为这是一种相当常见的做法-使用匿名函数或对象的函数作为RDD转换。