0x01 數(shù)據(jù)序列化調(diào)優(yōu)
在進(jìn)行RDD緩存和Shuffle過(guò)程時(shí),Spark會(huì)將數(shù)據(jù)對(duì)象進(jìn)行序列化,所以選擇合適的序列化方法,可以提高spark任務(wù)的性能。SPark提供了兩個(gè)序列化庫(kù):
原生Java序列化:默認(rèn)情況下Spark使用Java序列化庫(kù)。Java序列化很靈活,但是通常很慢,而且序列化格式很大。
Kryo序列化:與Java序列化相比,kryo速度更快(10倍左右),而且序列化格式更緊湊,序列化后數(shù)據(jù)包體更小。
使用:conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer"),如果對(duì)象很大,還需要增加spark.kryoserializer.buffer的大小。
0x02 內(nèi)存調(diào)優(yōu)
2.1調(diào)整數(shù)據(jù)結(jié)構(gòu)
1.如果Executor分配的內(nèi)存少于32G,可以設(shè)置JVM標(biāo)識(shí):-XX:+UseCompressedOops將對(duì)象指針設(shè)為4字節(jié)而不是8字節(jié)。
2.2 序列化RDD存儲(chǔ)
對(duì)于重復(fù)使用的RDD,將它緩存起來(lái)。
2.3 垃圾收集優(yōu)化
1.Spark的Storage和Execution內(nèi)存占用由spark.memory.fraction控制,應(yīng)該保證JVM的老年代的占用比例(NewRatio/(NewRatio+1))大于spark.memory.fraction。這樣能夠保證老年代有足夠的空間存放RDD緩存和Shuffle緩存的數(shù)據(jù),避免頻繁Full GC。
2.通過(guò)設(shè)置-XX:+UseG1GC來(lái)使用G1垃圾回收器。在堆內(nèi)存夠大時(shí),需要通過(guò)設(shè)置-XX:G1HeapRegionSize來(lái)增大G1區(qū)域大小。
3.如果任務(wù)是從HDFS中讀取數(shù)據(jù),通常每個(gè)HDFS數(shù)據(jù)塊(128M)對(duì)應(yīng)一個(gè)RDD的Partition(或者一個(gè)Task),解壓縮塊的大小通常是塊大小的2~3倍,而且每個(gè)Executor通常同時(shí)運(yùn)行3 ~ 4Task,所以我們可以估計(jì)Eden的大小為4*3*128MB。
0x03 其他調(diào)優(yōu)
3.1 并行度調(diào)優(yōu)
最理想的情況:Task數(shù)量和分配的CPU core數(shù)量相同,這樣所有的Task一起運(yùn)行,差不多同一時(shí)間運(yùn)行完畢。
但實(shí)際情況,有些task會(huì)運(yùn)行的快一些,有些task會(huì)運(yùn)行的慢一點(diǎn),如果task數(shù)量和cpu core的數(shù)量相同,就會(huì)導(dǎo)致一部分task運(yùn)行完后,這部分cpu core就空閑出來(lái)了,而且一直空閑到程序結(jié)束,就造成了資源浪費(fèi)。所以官方推薦Task數(shù)量設(shè)置成CPU core數(shù)量的2~3倍。盡量讓cpu不要空閑,同時(shí)提高Task的并發(fā)度,可以減少每個(gè)task處理的數(shù)據(jù)量,從而也可以提升運(yùn)行性能。
3.2 減少Task的內(nèi)存使用量
Spark自動(dòng)根據(jù)文件的大小設(shè)定了運(yùn)行在其上的map任務(wù)的數(shù)量,而對(duì)于reduce操作,例如groupByKey和reduceByKey,如果并行度過(guò)低,導(dǎo)致Task中的數(shù)據(jù)集太大,進(jìn)而導(dǎo)致OutofMemoryError。我們可以增加并行度,讓每個(gè)人物獲取到的數(shù)據(jù)集更小。而且多任務(wù)可以重用一個(gè)Executor JVM,任務(wù)的啟動(dòng)成本很低,因此可以安全地增加并行度到集群中的core數(shù)量。
3.3 廣播大變量
當(dāng)RDD算子中引用了Driver中的一個(gè)大的對(duì)象,每個(gè)Task都會(huì)持有這個(gè)大對(duì)象的序列化副本,導(dǎo)致Task序列化包體太大,可以通過(guò)Spark的廣播機(jī)制,將大對(duì)象廣播到每個(gè)Executor上,這樣可以減少Task的序列化包體。一般來(lái)說(shuō)大于20kb的Task有可能需要優(yōu)化。