【spark】序列化和反序列化,transient关键字的使用

序列化

Spark是基于JVM运行的进行,其序列化必然遵守Java的序列化规则。

序列化就是指将一个对象转化为二进制的byte流(注意,不是bit流),然后以文件的方式进行保存或通过网络传输,等待被反序列化读取出来。序列化常被用于数据存取和通信过程中

spark dirver和executor间传递变量,默认需要进行序列化,才能传递。不序列话的成员,可以通过添加@transientlazy标识。

在spark中4个地方用到了序列化:

  1. 算子中用到了driver定义的外部变量的时候
  2. 将自定义的类型作为RDD的泛型类型,所有的自定义类型对象都会进行序列化
  3. 使用可序列化的持久化策略的时候。比如:MEMORY_ONLY_SER,spark会将RDD中每个分区都序列化成一个大的字节数组。
  4. shuffle的时候

序列化的方法:

  1. 类继承scala.Serializable
  2. 使用case class修饰类,case class默认实现了序列化

transient 和 lazy

scala 中@transient 是 java 的 transient 关键字的作用,是需要实现 Serilizable 接口,@transient

是类型修饰符,只能用来修饰字段。在对象序列化过程中, 被 transient 标记的变量不会被序列化

transient使用小结

1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。(spark中反序列化后还可以访问吗?可以,但读到的是null。加上lazy才能访问到具体的值。)

2)transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。

3)被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。

@transient修饰符的lazy val的区别:

lazy val是一个懒加载的不可变值,在第一次访问时才会被计算并缓存起来,且只计算一次。而@transient修饰符则可以用来标记某些字段在序列化时忽略。

示例1:

scala 复制代码
class A(val a: Int)

def compute(rdd: RDD[Int]) = {
  // lazy val instance = {
  @transient lazy val instance = {
    println("in lazy object")
    new A(1)
  }
  val res = rdd.map(instance.a + _).count()
  println(res)
}

compute(sc.makeRDD(1 to 100, 8))

如果在driver端不使用instance,那么@transient 不是必须的,序列化会发生,这时候序列化的instance 为null。

在executor处使用的时候,才真正创建instance。

如果在driver端先使用了instance,那么@transient 是必须的。

示例2

scala 复制代码
 test("序列化") {

    class A(a: String) extends Serializable {
      @transient val name = a
      lazy val nanme2 = a
      val nanme3 = a
      @transient lazy val name4 = a
    }


    val sc = SparkSession.builder().enableHiveSupport().master("local").appName("JoinTest").getOrCreate()
    import sc.sqlContext.implicits._
    val a = new A("张三")
    val res = Seq("ddd").toDF("c1").map {
      x =>
        (a.name, a.nanme2, a.nanme3, a.name4)
    }.toDF("a", "b", "c", "d").show()
  }
  
+----+----+----+----+
|   a|   b|   c|   d|
+----+----+----+----+
|null|张三|张三|张三|
+----+----+----+----+

可以看到,不序列化的,在executor端读到的是null。

参考

Spark 序列化和kryo序列化器详解
Scala的序列化,Serialization以及SerialVersionUID
Spark序列化
Java transient关键字使用小记
Scala 序列化带有或不带有@transient修饰符的lazy val的区别
Scala and the '@transient lazy val' pattern
Difference when serializing a lazy val with or without @transient

相关推荐
Raas10012 小时前
MAI Gateway(魔芋企业级AI网关)技术揭秘:AI网关支持哪些模型?从原理到落地
大数据·人工智能·网关·gateway·mai gateway·企业级产品
YangYang9YangYan15 小时前
2026 校招商品分析岗位 JD 拆解,核心指标、工具与面试考点
大数据·数据库·数据分析
大大大大晴天15 小时前
OpenMetadata VS DataHub VS Atlas VS Gravitino
大数据
Qyr9918 小时前
2026全球汽车碳刷行业发展全景分析报告
大数据
蓝速科技19 小时前
便民服务大厅 AI 数字人一体机场景适配与落地指南丨蓝速科技
大数据·网络·数据结构·人工智能·自然语言处理·数据分析·运维开发
精益数智工坊19 小时前
云计算环境数据怎么同步?云计算集成方案有哪些?
大数据·人工智能·数据挖掘·数据可视化
huashengzsj20 小时前
什么是DMS经销商管理系统?国内经销商管理系统有哪些品牌
大数据
IT毕设梦工厂21 小时前
计算机毕业设计选题推荐:基于大数据的草鱼价格分析与可视化|毕业设计选题|计算机毕设|选题推荐|毕设指导|项目定制|源码|高质量项目
大数据·hadoop·python·数据挖掘·数据分析·课程设计·大数据毕设项目
辛迪聊物业数字化1 天前
智慧社区物业管理软件新手部署与实操指南
大数据·php
字节跳动数据平台1 天前
模型再强,为什么 Demo 还是进不了生产?
大数据