SparkConf.set("spark.serializer","org.apache.spark.serializer.KryoSerializer");
还可以进一步优化,优化这个序列化格式
默认情况下,Spark内部是使用Java的序列化机制,ObjectOutputStream/ObjectInputStream,对象输入输出流机制,来进行序列化
这种默认序列化机制的好处在于,处理起来比较方便;也不需要我们手动去做什么事情,只是,你在算子里面使用的变量,必须是实现Serializable接口的,可序列化即可。
但是缺点在于,默认的序列化机制的效率不高,序列化的速度比较慢,占用的内存空间还是比较大
可以进行手动进行序列化格式的优化
Spark支持使用Kryo序列化机制,Kryo序列化机制,比默认的Java序列化机制,速度要快,序列化后的数据要更小,大概是Java序列化机制的1/10
所以Kryo序列化优化以后,可以让网络传输的数据变少,在急群中耗费的内存资源大大减少
Kryo序列化机制:一旦启动,后边几个地方都会生效
1. 算子函数中使用到外部变量,需要序列化
2. 持久化RDD时进行序列化,StorageLevel.MEMORY_ONLY_SER
当使用了序列化持久化级别时,在将每个RDD partition序列化成一个大的字节数组时,就会使用Kryo进一步优化序列化的效率和性能
3. shuffle
在进行stage间的task的shuffle操作时,节点与节点间的task会互相大量通过网络拉取和传输文件,此时,这些数据既然通过网络传输,也是可能哟啊序列化的,就会使用Kryo序列化机制
每个节点有2个task,那么每个节点就有俩个partition
应用:
首先第一步:在sparkConf中设置一个属性:
set("spark.serializer","org.apache.spark.serializer.KryoSerializer");
Kryo之所以没有被作为默认的序列化类库的原因,主要是因为Kryo要求,如果达到它的最佳性能的话,那么就一定要注册你自定义的类(比如,你的算子函数中使用了外部自定义类型的对象变量,这是,就要求必须注册你的类,否则Kryo达不到最佳性能)
第二步,注册你使用到的,需要通过Kryo序列化的,一些自定义类
registerKryClasses(你自己定义的类new Class[]{})