问题很多,但是慢慢理解,慢慢解决。。
今天学习spark优化,过程中学习了Kryo优化---是我更深的理解了序列化的作用,做个笔记先:
之前学习的java的序列化,是通过关键字Serialization实现的[Serialization is the process of turning structured objects into a byte stream--序列化就是一个将结构对象转换成字节流的过程---这个过程可能添加描述信息或者删除重复的数据进行压缩都是有可能的]---hadoop在序列化的时候是通过Writable接口来实现。
序列化的三个作用--这三个总结的还是挺有点意思的:
1.作为一种持久化格式:一个对象被序列化以后,它的编码可以被存储到磁盘上,供以后反序列化用。
2. 作为一种通信数据格式:序列化结果可以从一个节点,通过网络被传递到另一个节点上。
3. 作为一种拷贝、克隆(clone)机制:将对象序列化到内存的缓存区中。然后通过反序列化,可以得到一个对已存对象进行深拷贝的新对象
我就这三个总结写一下spark学习过程中遇到的经历:
作为一种持久化格式:spark的DataFrame通过持久化为json和parquet来持久化数据:
val conf = new SparkConf().setMaster("local").setAppName(this.getClass.getName)
val sc = new SparkContext(conf)
val sqlContext = new SQLContext(sc)
/**
* 导入隐式转换,自动给RDD增加转换成DF的方法
*
*/
import sqlContext.implicits._
val studentDF=sc.textFile("SparkDemo\\data\\students.txt")
.map(_.split(","))
.map(s =>Student(s(0),s(1),s(2).toInt,s(3),s(4)))
.toDF()/**
* 保存为json
*
*/
studentDF
.repartition(3)
.write
.json("SparkDemo\\data\\out\\json")
/**
* parquet : 特殊的文件格式,跨平台,跨语言
* 文件里面存了数据的元数据,列的描述,同时对数据进行了压缩
*
*
*/
studentDF
.write
.parquet("SparkDemo\\data\\out\\parquet")
/**
* 读取parquet
*
*/
val pDF = sqlContext.read.parquet("bigdata/data/parquet")
通过将数据写成json或者parquet格式实现数据的持久化;
spark优化方法:使用Kryo优化序列化性能
在Spark中,主要有三个地方涉及到了序列化:
在算子函数中使用到外部变量时,该变量会被序列化后进行网络传输
将自定义的类型作为RDD的泛型类型时(比如JavaRDD,SXT是自定义类型),所有自定义类型对象,都会进行序列化。因此这种情况下,也要求自定义的类必须实现 Serializable接口。
使用可序列化的持久化策略时(比如MEMORY_ONLY_SER),Spark会将RDD中的每个 partition都序列化成一个大的字节数组。
Spark支持使用Kryo序列化机制。Kryo序列化机制,比默认的Java序列化机制,速度要快 ,序列化后的数据要更小,大概是Java序列化机制的1/10。所以Kryo序列化优化以后,可 以让网络传输的数据变少;在集群中耗费的内存资源大大减少。
对于这三种出现序列化的地方,我们都可以通过使用Kryo序列化类库,来优化序列化和 反序列化的性能。Spark默认使用的是Java的序列化机制,也就是 ObjectOutputStream/ObjectInputStream API来进行序列化和反序列化。但是Spark同时支持使用Kryo序列化库,Kryo序列化类库的性能比Java序列化类库的性能要高很多。 官方介绍,Kryo序列化机制比Java序列化机制,性能高10倍左右。Spark之所以默认没有 使用Kryo作为序列化类库,是因为Kryo要求最好要注册所有需要进行序列化的自定义类 型,因此对于开发者来说,这种方式比较麻烦