一削饵、背景
還可以進一步優(yōu)化加叁,優(yōu)化這個序列化格式
默認(rèn)情況下扮休,Spark內(nèi)部是使用Java的序列化機制,ObjectOutputStream / ObjectInputStream拴泌,對象輸入輸出流機制魏身,來進行序列化
這種默認(rèn)序列化機制的好處在于,處理起來比較方便蚪腐;也不需要我們手動去做什么事情箭昵,只是,你在算子里面使用的變量回季,必須是實現(xiàn)Serializable接口的家制,可序列化即可。
但是缺點在于泡一,默認(rèn)的序列化機制的效率不高颤殴,序列化的速度比較慢;序列化以后的數(shù)據(jù)鼻忠,占用的內(nèi)存空間相對還是比較大涵但。
可以手動進行序列化格式的優(yōu)化
- Spark支持使用Kryo序列化機制。Kryo序列化機制帖蔓,比默認(rèn)的Java序列化機制矮瘟,速度要快,序列化后的數(shù)據(jù)要更小塑娇,大概是Java序列化機制的1/10澈侠。
所以Kryo序列化優(yōu)化以后,可以讓網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)變少埋酬;在集群中耗費的內(nèi)存資源大大減少哨啃。
二、流程圖示
當(dāng)使用了序列化的持久化級別時写妥,在將每個RDD partition序列化成一個大的字節(jié)數(shù)組時拳球,就會使用Kryo進一步優(yōu)化序列化的效率和性能
在進行stage間的task的shuffle操作時,節(jié)點與節(jié)點之間的task會互相大量通過網(wǎng)絡(luò)拉取和傳輸文件珍特,此時醇坝,這些數(shù)據(jù)既然通過網(wǎng)絡(luò)傳輸,也是可能要序列化的次坡,就會使用Kryo
Kryo序列化機制呼猪,一旦啟用以后,會生效的幾個地方:
1砸琅、算子函數(shù)中使用到的外部變量
2宋距、持久化RDD時進行序列化,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í)行的時候,創(chuàng)建的對象琳省,就不至于頻繁的占滿內(nèi)存迎吵,頻繁發(fā)生GC。
3针贬、shuffle:可以優(yōu)化網(wǎng)絡(luò)傳輸?shù)男阅?/p>
三击费、實戰(zhàn)
SparkConf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
首先第一步,在SparkConf中設(shè)置一個屬性桦他,spark.serializer蔫巩,org.apache.spark.serializer.KryoSerializer類;
Kryo之所以沒有被作為默認(rèn)的序列化類庫的原因快压,就要出現(xiàn)了:主要是因為Kryo要求圆仔,如果要達到它的最佳性能的話,那么就一定要注冊你自定義的類(比如嗓节,你的算子函數(shù)中使用到了外部自定義類型的對象變量荧缘,這時,就要求必須注冊你的類拦宣,否則Kryo達不到最佳性能)截粗。
第二步,注冊你使用到的鸵隧,需要通過Kryo序列化的绸罗,一些自定義類,SparkConf.registerKryoClasses()
項目中的使用:
.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
.registerKryoClasses(new Class[]{CategorySortKey.class})