首頁(yè)技術(shù)文章正文

云計(jì)算大數(shù)據(jù)培訓(xùn)之Spark調(diào)優(yōu)(3)

更新時(shí)間:2017-09-01 來(lái)源:黑馬程序員云計(jì)算大數(shù)據(jù)培訓(xùn)學(xué)院 瀏覽量:

四,廣播大變量 

使用背景:當(dāng)RDD 引用到了一個(gè)外部變量,并且這個(gè)外部變量數(shù)據(jù)量還不小,同時(shí)這個(gè)RDD對(duì)應(yīng)的task數(shù)量特別多,那么此時(shí)使用廣播變量就在合適不過(guò)了

使用原理:因?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è)失敗的概率,如何解決以上的問(wèn)題?也就是什么時(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è)失敗的概率

使用過(guò)程: 
1、某個(gè)executor的第一個(gè)task先執(zhí)行的時(shí)候,首先從自己的blockManager中查找外部變量,如果沒(méi)有就從鄰居的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ī)制,來(lái)進(jìn)行序列化 
這種默認(rèn)的序列化機(jī)制的好處在于,處理起來(lái)比較方便,也不需要手動(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之所以沒(méi)有被作為默認(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è)你使用到的。需要通過(guò)Kryo序列化的,一些自定義類: 
sparkConf.registerKryoClasses() 
例如:sparkConf.registerKryoClasses(Array(classOf[CategorySecondSort],classOf[…]))


本文版權(quán)歸黑馬程序員云計(jì)算大數(shù)據(jù)培訓(xùn)學(xué)院所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明作者出處。謝謝!
作者:黑馬程序員云計(jì)算大數(shù)據(jù)培訓(xùn)學(xué)院
首發(fā):http://cloud.itheima.com/ 
分享到:
在線咨詢 我要報(bào)名
和我們?cè)诰€交談!