更新時(shí)間:2017-09-01 來源:黑馬程序員云計(jì)算大數(shù)據(jù)培訓(xùn)學(xué)院 瀏覽量:
使用背景:當(dāng)RDD 引用到了一個(gè)外部變量,并且這個(gè)外部變量數(shù)據(jù)量還不小,同時(shí)這個(gè)RDD對(duì)應(yīng)的task數(shù)量特別多,那么此時(shí)使用廣播變量就在合適不過了
使用原理:因?yàn)槊總€(gè)task都要拷貝一個(gè)副本到executor去執(zhí)行,那么我們可以想象一下,如果有1000個(gè)task在某個(gè)worker上執(zhí)行,而這個(gè)副本有100M,那么就意味著我們要拷貝100G的數(shù)據(jù)到某個(gè)worker上去執(zhí)行,這樣的話會(huì)大大消耗我們的網(wǎng)絡(luò)流量,同時(shí)會(huì)加大executor的內(nèi)存消耗,從而增加我們spark作業(yè)的運(yùn)行時(shí)間,大大降低了spark作業(yè)的運(yùn)行效率,增加了作業(yè)失敗的概率,如何解決以上的問題?也就是什么時(shí)候該使用廣播變量,我們可以將這種大的外部變量做成廣播變量,那么每個(gè)executor的內(nèi)存中只會(huì)有一個(gè)外部變量,這樣的一個(gè)副本,針對(duì)所有的task都是共享的,這樣的話就減少了網(wǎng)絡(luò)流量的消耗,降低了executor的內(nèi)存消耗,提高了spark 作業(yè)運(yùn)行效率和 縮短了運(yùn)行時(shí)間,同時(shí)降低了作業(yè)失敗的概率
使用過程:
1、某個(gè)executor的第一個(gè)task先執(zhí)行的時(shí)候,首先從自己的blockManager中查找外部變量,如果沒有就從鄰居的executor的blockManager的內(nèi)存中獲取這個(gè)外部變量,如果還是獲取不到,就從driver端獲取,拷貝這個(gè)外部變量到本地的executor的blockManager中
2、當(dāng)這個(gè)executor的其他task執(zhí)行時(shí),就不需要再?gòu)耐饷娅@取這個(gè)外部變量的副本了,直接從本地的blockManager中獲取即可
【注意】廣播變量可讀,不可寫
五,使用Kryo序列化
默認(rèn)情況下,spark內(nèi)部是使用Java的序列化機(jī)制,objectOutputStream/ObjectInputStream對(duì)象輸入輸出機(jī)制,來進(jìn)行序列化
這種默認(rèn)的序列化機(jī)制的好處在于,處理起來比較方便,也不需要手動(dòng)去做什么事情,只是,你在算子里面使用的變量,必須實(shí)現(xiàn)Serializable接口的,可序列化即可
但是缺點(diǎn)是,默認(rèn)的序列化的效率不高,序列化速度比較慢,序列化以后的數(shù)據(jù),占用的內(nèi)存空間相對(duì)還是比較大的
Spark支持使用Kryo序列化機(jī)制。
Kyro序列化機(jī)制,比默認(rèn)的Java序列化機(jī)制,速度要快,序列化后的數(shù)據(jù)要更小,大概是Java序列化機(jī)制的1/10。所以Kryo序列化優(yōu)化以后,可以讓網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)變少,在集群中耗費(fèi)的內(nèi)存資源大大減少
Kryo序列化機(jī)制,一旦啟用以后,會(huì)生效的幾個(gè)地方:
1、算子函數(shù)中使用到的外部變量
2、持久化RDD時(shí)進(jìn)行序列化,StorageLevel.MEMORY_ONLY_SER
3、Shuffle
1、算子函數(shù)中使用到的外部變量,使用Kryo以后:優(yōu)化網(wǎng)絡(luò)傳輸?shù)男阅埽梢詢?yōu)化集群中的內(nèi)存的占用和消耗
2、持久化RDD,優(yōu)化內(nèi)存的占用和消耗,持久化RDD占用的內(nèi)存越少,task執(zhí)行的時(shí)候,創(chuàng)建的對(duì)象,就不至于頻繁的占滿內(nèi)存,頻繁的發(fā)生GC
3、Shuffle:可以優(yōu)化網(wǎng)絡(luò)傳輸?shù)男阅?nbsp;
Kryo之所以沒有被作為默認(rèn)的序列化類庫(kù)的原因:
主要是因?yàn)镵ryo要求,如果要達(dá)到他的最佳性能的話,那么就一定要注冊(cè)你自定義的類(比如,你的算子函數(shù)中使用到了外部自定義的對(duì)象變量,這時(shí),就要求必須注冊(cè)你的類,否則Kryo達(dá)不到最佳的性能)。
首先,第一步:在sparkConf中設(shè)置一個(gè)屬性:
spark.serializer,org.apache.spark.serializer.KryoSerializer類
例如:sparkConf.set(“spark.serializer”,”org.apahe.spark.serializer.KryoSerializer”)
其次,第二步:注冊(cè)你使用到的。需要通過Kryo序列化的,一些自定義類:
sparkConf.registerKryoClasses()
例如:sparkConf.registerKryoClasses(Array(classOf[CategorySecondSort],classOf[…]))
云計(jì)算大數(shù)據(jù)培訓(xùn)之Spark調(diào)優(yōu)(2)
2017-09-01云計(jì)算大數(shù)據(jù)培訓(xùn)之Spark調(diào)優(yōu)(1)
2017-09-01云計(jì)算大數(shù)據(jù)培訓(xùn)之Hadoop組件:zookeeper(3)
2017-09-01云計(jì)算大數(shù)據(jù)培訓(xùn)之Hadoop組件:zookeeper(2)
2017-09-01云計(jì)算大數(shù)據(jù)培訓(xùn)之Hadoop組件:zookeeper(1)
2017-09-01云計(jì)算大數(shù)據(jù)培訓(xùn)之Spark-Streaming的基本原理以及預(yù)寫日志機(jī)制和checkpoint(3)
2017-09-01