【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

相关推荐
Data_Journal18 小时前
什么是 CAPTCHA,它是如何工作的?
java·大数据·服务器·前端·数据库
跨境小彭18 小时前
店群运营实操复盘:批量活动申报自动化优化方案
大数据·运维·人工智能·自动化·跨境电商·temu·temu电商运营
Eric.4619 小时前
Stable Diffusion+ComfyUI+OpenClaw AI漫剧量产提示词工程:结构化Prompt、负面词脱敏、权重锁定防画面崩坏全方案
大数据·人工智能·stable diffusion·prompt·comfyui·ai漫剧
长谷深风11119 小时前
ReAct框架:让AI像人类一样思考与行动
大数据·人工智能·热门·ai agent·agent工作流·智能体设计·ai产品设计
办公室马主任19 小时前
乐图数字化打通哪几个环节?从车间数据到经营决策的数据链路设计
大数据·人工智能·系统架构·制造
delishcomcn19 小时前
数字孪生+AI预测:热烫膜分切机迈向“黑灯工厂”的关键路径
大数据·人工智能
Raas10020 小时前
MAI Gateway(魔芋企业级AI网关):企业AI网关的合规审计与调用留痕设计
大数据·人工智能·gateway·企业·api网关·mai gateway·企业级网关
Irene199120 小时前
剑指大数据:企业级数据仓库项目实战(金融租赁版)读书笔记__大数据测试集群的服务器节点服务分配规划表__解读(附:技术选型清单)
大数据·数据仓库·金融
小五传输20 小时前
Serv-U替代方案怎么选?政务机关文件安全传输对比与迁移指南
大数据·运维·安全
吉甫作诵20 小时前
阿里云 ECS 安装 ClickHouse:密码配置、目录迁移与基础调优
大数据·clickhouse