文章地址:http://www.haha174.top/article/details/254551
<http://www.haha174.top/article/details/254551>


在任何分布式系统里面序列化都是扮演一个很重要的角色。如果使用序列化的技术,在执行序列化的时候很慢,或者序列化之后数据量还是很大。那么会让分布式应用程序的性能下降很多。所以进行spark性能优化的第一步。就是进行序列化的性能优化。

spark自身默认在一些地方会进行序列化,比如Shuffle
。还有就是如果我们的算子函数使用到了分外部的数据(比如java的内村类型,或者自定义类型)那么也需要让其可以序列化。


而spark自身对于序列化的便捷性和性能做了一些的取舍和权衡。默认,spark倾向于序列化的便捷性,使用了java自身提供的序列化机制–基于ObjectInputStream和ObjectOutputStream的序列化机制因为这种机制是Java
原生提供的很方便使用。

但是java 原生的序列化机制性能并不高。序列化速度相对较慢。而且序列化之后还是比较占用内存的。因此如果你的spark应用程序对内存很敏感那么java
默认的序列化机制不是最好的选择。

spark 提供了两种序列化机制,它默认使用了第一种
1. java 序列化机制:默认情况下Spark
使用java自身的ObjectInputStream和ObjectOutputStream机制机型java对象的序列化。只要你的类实现了Serializable接口,那么都是可以序列化的,而且java的序列化机制是提供了自定义序列化支持的,只要你实现Externalizable接口即可实现自己的更高的性能的序列化算法。java的序列化机制的速度比较慢而且序列化后数据占用的空间内存比较大。
2.
Kryo序列化机制:spark也支持使用kryo类库来进行序列化。kryo序列化机制比java序列化机制更快。而且序列化后占用的空间更小,通常比java序列化的数据占用的空间要小上10倍。kryo序列化机制之所以不是默认序列化机制的原因是有些类虽然实现了Seriralizable
接口但是它也不一定能够进行序列化;此外如果要得到最佳的性能。kryo还要求你在spark应用中对所有需要序列化的类都进行注册。

如果要使用kryo序列化机制,首先要sparkconf设置一个参数使用new
SparkConf().set(“spark.serializer”,”org.apache.spark.serializer.KryoSerializer”)即可,即将spark的序列化设置为KryoSerializer这样Spark在内部的一些操作比如shuffle进行序列化的时候就会使用kryo类库进行高兴能,快速,更低占用量的序列化了。


使用kryo时,它要求是需要序列化的类,是要预先进行注册的,以获得最佳–如果不注册的话。那么kryo必须时刻保存类型的全限定明,反而占用不少内存。spark默认是对Scala中常用的类型自动注册了kryo的,都在AllScalaRegistry。类中

但是比如自己的算子中,使用了外部的自定义类型的对象。那么还是需要将其进行注册。


优化kryo类库的使用
(1).优化缓存大小

如果注册的要序列化的自定义的类型本身很大,比如超过100个field那么会导致这个序列化对象过大此时需要对kryo本身进行优化。因为kryo的内部的缓存可能不够存放这么大的class对象此时需要调用SparkConf.set()方法,设置spark.kryoserializer.buffer.mb参数的值。将其调大。
默认情况下他的值是2 就是说最大2M的缓存对象然后进行序列化。可以在必要的时候将其调大比如设置为10.
预先自定义类型。

虽然不注册自定义类型,kryo类库也能正常的工作,但是那样的话对于它要序列化的每个对象都会保存一份他的全限定类名,此时反而会消耗大量内存,因此通常都建议预先注册要序列化的自定义的类.

欢迎关注,更多福利