1. 程式人生 > >Spark 效能相關引數配置詳解-壓縮與序列化篇

Spark 效能相關引數配置詳解-壓縮與序列化篇

作者:劉旭暉 Raymond 轉載請註明出處

隨著Spark的逐漸成熟完善越來越多的可配置引數被新增到Spark中來本文試圖通過闡述這其中部分引數的工作原理和配置思路和大家一起探討一下如何根據實際場合對Spark進行配置優化。

壓縮和序列化相關

spark.serializer

預設為org.apache.spark.serializer.JavaSerializer, 可選org.apache.spark.serializer.KryoSerializer, 實際上只要是org.apache.spark.serializer的子類就可以了,不過如果只是應用,大概你不會自己去實現一個的。

序列化對於

spark應用的效能來說,還是有很大影響的,在特定的資料格式的情況下,KryoSerializer的效能可以達到JavaSerializer10倍以上,當然放到整個Spark程式中來考量,比重就沒有那麼大了,但是以Wordcount為例,通常也很容易達到30%以上的效能提升。而對於一些Int之類的基本型別資料,效能的提升就幾乎可以忽略了。KryoSerializer依賴TwitterChill庫來實現,相對於JavaSerializer,主要的問題在於不是所有的Java Serializable物件都能支援。

需要注意的是,這裡可配的Serializer針對的物件是Shuffle資料,以及RDD Cache

等場合,而Spark Task的序列化是通過spark.closure.serializer來配置,但是目前只支援JavaSerializer,所以等於沒法配置啦。

spark.rdd.compress

這個引數決定了RDD Cache的過程中,RDD資料在序列化之後是否進一步進行壓縮再儲存到記憶體或磁碟上。當然是為了進一步減小Cache資料的尺寸,對於Cache在磁碟上而言,絕對大小大概沒有太大關係,主要是考慮DiskIO頻寬。而對於Cache在記憶體中,那主要就是考慮尺寸的影響,是否能夠Cache更多的資料,是否能減小Cache資料對GC造成的壓力等。

這兩者,前者通常不會是主要問題,尤其是在

RDD Cache本身的目的就是追求速度,減少重算步驟,用IOCPU的情況下。而後者,GC問題當然是需要考量的,資料量小,佔用空間少,GC的問題大概會減輕,但是是否真的需要走到RDDCache壓縮這一步,或許用其它方式來解決可能更加有效。

所以這個值預設是關閉的,但是如果在磁碟IO的確成為問題或者GC問題真的沒有其它更好的解決辦法的時候,可以考慮啟用RDD壓縮。

spark.broadcast.compress

是否對Broadcast的資料進行壓縮,預設值為True

Broadcast機制是用來減少執行每個Task時,所需要傳送給TASKRDD所使用到的相關資料的尺寸,一個Executor只需要在第一個Task啟動時,獲得一份Broadcast資料,之後的Task都從本地的BlockManager中獲取相關資料。在1.1最新版本的程式碼中,RDD本身也改為以Broadcast的形式傳送給Executor(之前的實現RDD本身是隨每個任務傳送的),因此基本上不太需要顯式的決定哪些資料需要broadcast了。

因為Broadcast的資料需要通過網路傳送,而在Executor端又需要儲存在本地BlockMananger中,加上最新的實現,預設RDD通過Boradcast機制傳送,因此大大增加了Broadcast變數的比重,所以通過壓縮減小尺寸,來減少網路傳輸開銷和記憶體佔用,通常都是有利於提高整體效能的。

什麼情況可能不壓縮更好呢,大致上個人覺得同樣還是在網路頻寬和記憶體不是問題的時候,如果DriverCPU資源很成問題(畢竟壓縮的動作基本都在Driver端執行),那或許有調整的必要。

spark.io.compression.codec

RDD CacheShuffle資料壓縮所採用的演算法Codec,預設值曾經是使用LZF作為預設Codec,最近因為LZF的記憶體開銷的問題,預設的Codec已經改為Snappy

LZFSnappy相比較,前者壓縮率比較高(當然要看具體資料內容了,通常要高20%左右),但是除了記憶體問題以外,CPU代價也大一些(大概也差20%~50%?)

在用於Shuffle資料的場合下,記憶體方面,應該主要是在使用HashShuffleManager的時候有可能成為問題,因為如果Reduce分割槽數量巨大,需要同時開啟大量的壓縮資料流用於寫檔案,進而在Codec方面需要大量的buffer。但是如果使用SortShuffleManager,由於shuffle檔案數量大大減少,不會產生大量的壓縮資料流,所以記憶體開銷大概不會成為主要問題。

剩下的就是CPU和壓縮率的權衡取捨,和前面一樣,取決於CPU/網路/磁碟的能力和負載,個人認為CPU通常更容易成為瓶頸。所以要調整效能,要不不壓縮,要不使用Snappy可能性大一些?

對於RDD Cache的場合來說,絕大多數場合都是記憶體操作或者本地IO,所以CPU負載的問題可能比IO的問題更加突出,這也是為什麼spark.rdd.compress 本身預設為不壓縮,如果要壓縮,大概也是Snappy合適一些?