Spark效能優化三之採用kryo序列化類庫
Spark自身預設會在一些地方對資料進行序列化,比如Shuffle。還有就是,如果我們的運算元函式使用到了外部的資料,比如我們在外部定義了一個封裝了應用所有配置的物件,自定義了一個MyConfiguration物件,裡面包含了100m的資料。然後,在運算元函式裡面,使用到了這個外部的大物件,那麼也需要讓其可序列化。 Spark提供了兩種序列化機制,預設使用第一種: 1、Java序列化機制: 只要你的類實現了Serializable介面,那麼都是可以序列化的 但是問題是,Java序列化機制的效能並不高。序列化的速度相對較慢,而且序列化以後的資料,還是相對來說比較大,還是比較佔用記憶體空間。因此,如果你的Spark應用程式對記憶體很敏感,那麼預設的Java序列化機制並不是最好的選擇 2、Kryo序列化機制:Spark也支援使用Kryo類庫來進行序列化。Kryo序列化機制比Java序列化機制更快,而且序列化後的資料佔用的空間更小,通常比Java序列化的資料佔用的空間要小10倍。 如果要使用Kryo序列化機制,使用new SparkConf().set(“spark.serializer”, “org.apache.spark.serializer.KryoSerializer”)即可,即將Spark的序列化器設定為KryoSerializer。這樣,Spark在內部的一些操作,比如Shuffle,進行序列化時,就會使用Kryo類庫進行高效能、快速、更低記憶體佔用量的序列化了。使用Kryo時,它要求是需要序列化的類,是要預先進行註冊的,以獲得最佳效能——如果不註冊的話,那麼Kryo必須時刻儲存型別的全限定名,反而佔用不少記憶體。 如果要註冊自定義的型別,那麼就使用如下的程式碼,即可: Scala版本: val conf = new SparkConf().setMaster(…).setAppName(…) conf.registerKryoClasses(Array(classOf[Counter] )) val sc = new SparkContext(conf) Java版本: SparkConf conf = new SparkConf().setMaster(…).setAppName(…) conf.registerKryoClasses(Counter.class) JavaSparkContext sc = new JavaSparkContext(conf) 如果註冊的要序列化的自定義的型別,本身特別大,比如包含了超過100個field。那麼就會導致要序列化的物件過大。此時就需要對Kryo本身進行優化。因為Kryo內部的快取可能不夠存放那麼大的class物件。此時就需要呼叫SparkConf.set()方法,設定spark.kryoserializer.buffer.mb引數的值,將其調大。 預設情況下它的值是2,就是說最大能快取2M的物件,然後進行序列化。可以在必要時將其調大。比如設定為10。