首页技术文章正文

云计算大数据培训之Spark调优(3)

更新时间:2017-09-01 来源:黑马程序员云计算大数据培训学院 浏览量:

四,广播大变量 

使用背景:当RDD 引用到了一个外部变量,并且这个外部变量数据量还不小,同时这个RDD对应的task数量特别多,那么此时使用广播变量就在合适不过了

使用原理:因为每个task都要拷贝一个副本到executor去执行,那么我们可以想象一下,如果有1000个task在某个worker上执行,而这个副本有100M,那么就意味着我们要拷贝100G的数据到某个worker上去执行,这样的话会大大消耗我们的网络流量,同时会加大executor的内存消耗,从而增加我们spark作业的运行时间,大大降低了spark作业的运行效率,增加了作业失败的概率,如何解决以上的问题?也就是什么时候该使用广播变量,我们可以将这种大的外部变量做成广播变量,那么每个executor的内存中只会有一个外部变量,这样的一个副本,针对所有的task都是共享的,这样的话就减少了网络流量的消耗,降低了executor的内存消耗,提高了spark 作业运行效率和 缩短了运行时间,同时降低了作业失败的概率

使用过程: 
1、某个executor的第一个task先执行的时候,首先从自己的blockManager中查找外部变量,如果没有就从邻居的executor的blockManager的内存中获取这个外部变量,如果还是获取不到,就从driver端获取,拷贝这个外部变量到本地的executor的blockManager中 
2、当这个executor的其他task执行时,就不需要再从外面获取这个外部变量的副本了,直接从本地的blockManager中获取即可

【注意】广播变量可读,不可写

五,使用Kryo序列化 
默认情况下,spark内部是使用Java的序列化机制,objectOutputStream/ObjectInputStream对象输入输出机制,来进行序列化 
这种默认的序列化机制的好处在于,处理起来比较方便,也不需要手动去做什么事情,只是,你在算子里面使用的变量,必须实现Serializable接口的,可序列化即可 
但是缺点是,默认的序列化的效率不高,序列化速度比较慢,序列化以后的数据,占用的内存空间相对还是比较大的 
Spark支持使用Kryo序列化机制。 
Kyro序列化机制,比默认的Java序列化机制,速度要快,序列化后的数据要更小,大概是Java序列化机制的1/10。所以Kryo序列化优化以后,可以让网络传输的数据变少,在集群中耗费的内存资源大大减少

Kryo序列化机制,一旦启用以后,会生效的几个地方: 
1、算子函数中使用到的外部变量 
2、持久化RDD时进行序列化,StorageLevel.MEMORY_ONLY_SER 
3、Shuffle

1、算子函数中使用到的外部变量,使用Kryo以后:优化网络传输的性能,可以优化集群中的内存的占用和消耗 
2、持久化RDD,优化内存的占用和消耗,持久化RDD占用的内存越少,task执行的时候,创建的对象,就不至于频繁的占满内存,频繁的发生GC 
3、Shuffle:可以优化网络传输的性能 
Kryo之所以没有被作为默认的序列化类库的原因: 
主要是因为Kryo要求,如果要达到他的最佳性能的话,那么就一定要注册你自定义的类(比如,你的算子函数中使用到了外部自定义的对象变量,这时,就要求必须注册你的类,否则Kryo达不到最佳的性能)。

首先,第一步:在sparkConf中设置一个属性: 
spark.serializer,org.apache.spark.serializer.KryoSerializer类 
例如:sparkConf.set(“spark.serializer”,”org.apahe.spark.serializer.KryoSerializer”)

其次,第二步:注册你使用到的。需要通过Kryo序列化的,一些自定义类: 
sparkConf.registerKryoClasses() 
例如:sparkConf.registerKryoClasses(Array(classOf[CategorySecondSort],classOf[…]))


本文版权归黑马程序员云计算大数据培训学院所有,欢迎转载,转载请注明作者出处。谢谢!
作者:黑马程序员云计算大数据培训学院
首发:http://cloud.itheima.com/ 
分享到:
在线咨询 我要报名
和我们在线交谈!