https://spark.apache.org/docs/latest/tuning.html#data-serialization
Spark 需要在 Executor 和 Driver 之间传输数据,必然是涉及到序列化的问题。序列化后数据的大小和反序列执行的速度肯定对整个 Spark 作业有很大的影响。Spark 提供两种序列化方式:
- java 序列化:spark 默认使用 Java’s ObjectOutputStream,但也可以继承java.io.Serializable 来自定义并使用 java.io.Externalizable 使序列化的数据结构更紧密。Java 序列化可以做到很灵活,但其执行速度慢且占据空间大。
- Kryo 序列化:相比于 Java 序列化,执行速度更快占据空间更小,但需要使用 register 你需要的类才能达到更优的性能。在 2.0.0 开始,在处理简单类型时,spark 内部已使用的是
Kryo
。
测试
在讲解两种序列化的优缺点之后,我们写代码来测试看看
Java
seriRdd.persist()
查看 seriRdd
占用内存
序列化存储
seriRdd.persist(StorageLevel.MEMORY_ONLY_SER)
很显然,序列化后占用内存减少了(但反序列化是要时间的)
Kryo
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
seriRdd.persist(StorageLevel.MEMORY_ONLY_SER)
虽然使用了 KryoSerializer
,但没有注册,占用的空间比 java 序列化还大。那来看看注册之后的对比
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
conf.registerKryoClasses(Array(classOf[TestSerialization]))
seriRdd.persist(StorageLevel.MEMORY_ONLY_SER)
当注册之后,内存占用还是下降蛮多。切记使用 Kryo
一定要注册。
总结下占用内存,从大到小排序
- 没序列化
234 M
- 使用 Kryo 序列化,但没注册
156.8 M
- 使用 Java 序列化
67.4 M
- 使用 Kryo 序列化并注册
32.3 M