Spark優(yōu)化官方指導(dǎo)(Tuning Spark翻譯)

因?yàn)榇蠖鄶?shù)的Spark計(jì)算是在內(nèi)存中進(jìn)行的,所以Spark應(yīng)用的瓶頸在于集群的硬件資源:CPU、網(wǎng)絡(luò)帶寬或者內(nèi)存。在大多數(shù)情況下,如果內(nèi)存夠用费薄,網(wǎng)絡(luò)帶寬就會(huì)成為應(yīng)用性能的瓶頸硝全,但在有些時(shí)候,你仍然需要去做一些調(diào)整楞抡,比如用序列化的形式去存儲(chǔ)RDD伟众,以減少內(nèi)存的使用。這篇指導(dǎo)將覆蓋兩個(gè)主題:數(shù)據(jù)的序列化(數(shù)據(jù)的序列化方式是好的網(wǎng)絡(luò)性能以及減少內(nèi)存使用的關(guān)鍵)和內(nèi)存調(diào)整召廷。我們也會(huì)討論幾個(gè)小的主題凳厢。

Data Serialization(數(shù)據(jù)序列化)

在任何的分布式應(yīng)用的性能方面,序列化方式都扮演者一個(gè)極為重要的角色竞慢。如果序列化方式解析對(duì)象的速度太慢或者消耗的字節(jié)數(shù)量過大先紫,將會(huì)極大的放慢計(jì)算的速度。通常筹煮,這將是你在優(yōu)化Spark程序時(shí)需要優(yōu)先考慮調(diào)整的地方遮精。Spark的目標(biāo)是平衡便利(允許你使用任何Java中的類型進(jìn)行操作)和性能。他提供了兩種序列化庫(kù):

  • Java serialization:Spark的默認(rèn)的對(duì)象序列化方式是使用Java的ObjectOutputStream 框架,這種方式允許你使用任何實(shí)現(xiàn)了java.io.Serializable接口的類本冲。Java serialization非常靈活但速度太慢准脂,并且會(huì)導(dǎo)致很多的類的序列化結(jié)果太大。
  • Kryo serialization:Spark同時(shí)提供了Kryo庫(kù)(版本號(hào)4)來使對(duì)象的序列化速度更快檬洞。Kryo和Java serialization比較狸膏,顯著的加快了對(duì)象序列化的方式,并大大降低了序列化結(jié)構(gòu)的大刑碚(大于10倍)湾戳,但是Kryo并不支持所有可序列化的類型,并且他要求你注冊(cè)你希望改善性能的那些類澎灸。

你可以在初始化Spark作業(yè)的時(shí)候通過調(diào)用SparkConfset("spark.serializer", "org.apache.spark.serializer.KryoSerializer")來切換Kryo序列化方式院塞。這項(xiàng)配置不僅僅更改了工作節(jié)點(diǎn)之間進(jìn)行數(shù)據(jù)混洗的時(shí)候所用的序列化器,同時(shí)更改了將RDD寫入磁盤的時(shí)候的序列化器性昭。Spark沒有將Kryo作為默認(rèn)的序列化器的原因在于需要開發(fā)者自己注冊(cè)需要序列化的類型拦止,所以我們建議在IO密集型的應(yīng)用中使用Kryo作為序列化器。從Spark2.0.0開始糜颠,我們?cè)趦?nèi)部開始使用Kryo序列化器作為混洗簡(jiǎn)單數(shù)據(jù)類型及其數(shù)組類型的RDD的序列化器汹族。

Spark自動(dòng)包含了來自于Twitter chill庫(kù)中的常用的Scala類的Kryo序列化器的注冊(cè)。

要將你自己的類注冊(cè)成Kryo序列化支持的類其兴,可以使用registerKryoClasses方法顶瞒。

val conf = new SparkConf().setMaster(...).setAppName(...)
conf.registerKryoClasses(Array(classOf[MyClass1], classOf[MyClass2]))
val sc = new SparkContext(conf)

Kryo documentation中描述了更多的高級(jí)選項(xiàng),例如添加定制的序列化代碼元旬。

如果你的對(duì)象列表很大榴徐,你可能需要增加spark.kryoserializer.buffer config,這些配置需要你設(shè)置足夠大的值來存儲(chǔ)你將要序列化的對(duì)象匀归。
最后坑资,如果你沒有注冊(cè)你定制的類型,Kryo仍然可以工作穆端,但是袱贮,Kryo將會(huì)為每一個(gè)對(duì)象存儲(chǔ)完整的類名稱,這將會(huì)帶來浪費(fèi)体啰。

Memory Tuning(內(nèi)存優(yōu)化)

在進(jìn)行內(nèi)存優(yōu)化的時(shí)候有三個(gè)需要考慮的方面:你的數(shù)據(jù)對(duì)象所需要使用的內(nèi)存總數(shù)攒巍,訪問這些對(duì)象的花銷以及垃圾收集機(jī)制(如果你需要對(duì)這些數(shù)據(jù)對(duì)象進(jìn)行頻繁的轉(zhuǎn)換)
默認(rèn)情況下,Java對(duì)象可以快速的進(jìn)行訪問荒勇,但是比起停留在原位置的原始數(shù)據(jù)來說柒莉,Java對(duì)象會(huì)消耗2-5倍的空間。這是因?yàn)槿缦聨讉€(gè)原因:

  • 每一個(gè)不同的Java對(duì)象都包含一個(gè)對(duì)象頭沽翔,這個(gè)對(duì)象頭占用16個(gè)字節(jié)的空間常柄,包含了指向其類型的指針等信息。對(duì)于一個(gè)只包含了很少數(shù)據(jù)的對(duì)象來說,對(duì)象頭的空間會(huì)大于數(shù)據(jù)占用的空間西潘。
  • Java字符串比原始的字符數(shù)據(jù)多使用了40字節(jié)的空間卷玉,因?yàn)橐鎯?chǔ)字符數(shù)組相關(guān)的一系列信息,例如字符串長(zhǎng)度喷市,并且將每一個(gè)字符占用2個(gè)字節(jié)的空間相种,因?yàn)镴ava內(nèi)部的字符編碼使UTF-16 。因此一個(gè)超過10個(gè)字符的字符串對(duì)象會(huì)很容易的占用60個(gè)字節(jié)的空間
  • 通用的集合類品姓,比如HashMap和LinkedList寝并,使用鏈接式的數(shù)據(jù)結(jié)構(gòu),這些集合內(nèi)部存儲(chǔ)的每一個(gè)元素都是封裝過的對(duì)象(比如Map.Entry)腹备,這些對(duì)象不僅僅包含一個(gè)對(duì)象頭衬潦,而且還包含一個(gè)指向列表中下一個(gè)節(jié)點(diǎn)的指針(一般是8個(gè)字節(jié))。
  • 主要類型的集合通常將他們以裝箱的形式進(jìn)行存儲(chǔ)植酥,比如java.lang.Integer镀岛。

本章將開始對(duì)Spark的內(nèi)存管理進(jìn)行綜述,然后討論一些可以使用戶在Spark應(yīng)用中更有效的使用內(nèi)存的策略友驮。我們會(huì)著重描述如何確定應(yīng)用中的對(duì)象的內(nèi)存使用情況以及優(yōu)化她們的方法 - 這些方法要么是改變數(shù)據(jù)的結(jié)構(gòu)漂羊,要么是通過序列化的方式來存儲(chǔ)數(shù)據(jù)。然后我們將介紹如何調(diào)整Spark的緩存大小和Java的垃圾收集機(jī)制卸留。

Memory Management Overview(內(nèi)存管理綜述)

Spark中大多數(shù)的內(nèi)存使用分為兩類:執(zhí)行和存儲(chǔ)走越。執(zhí)行內(nèi)存主要用與計(jì)算中的混洗,連接耻瑟,排序和聚合等操作旨指,存儲(chǔ)內(nèi)存主要用來緩存數(shù)據(jù)以及在集群內(nèi)部傳播數(shù)據(jù)。在Spark中喳整,執(zhí)行和存儲(chǔ)共享統(tǒng)一的內(nèi)存區(qū)域谆构。如果執(zhí)行器沒有使用內(nèi)存,那么存儲(chǔ)功能能夠請(qǐng)求所有可用的內(nèi)存(如果存儲(chǔ)功能沒有使用任何內(nèi)存算柳,執(zhí)行功能也可以請(qǐng)求所有可用內(nèi)存)。當(dāng)然執(zhí)行功能在內(nèi)存的使用方面對(duì)存儲(chǔ)功能具有優(yōu)先權(quán)姓言,如果必要的話執(zhí)行功能可以搶占存儲(chǔ)功能占用的內(nèi)存瞬项,但是只能講存儲(chǔ)占用的內(nèi)存降低到一個(gè)閾值,無法完全搶占何荚。換句話說囱淋,內(nèi)存中有一個(gè)子區(qū)域的緩存塊將永遠(yuǎn)無法被搶占。存儲(chǔ)無法搶占執(zhí)行功能的內(nèi)存餐塘,這是因?yàn)橛?jì)算實(shí)現(xiàn)的復(fù)雜度造成的妥衣。

盡管有兩項(xiàng)相關(guān)的配置,但是對(duì)于絕大多數(shù)工作來說,不建議用戶去調(diào)整配置的默認(rèn)值税手。

  • spark.memory.fraction表示Spark作業(yè)使用的內(nèi)存區(qū)域與Jvm堆內(nèi)存的占比(默認(rèn)值是0.6)蜂筹。剩余的空間(40%)用來存儲(chǔ)用戶的數(shù)據(jù)結(jié)構(gòu),Spark內(nèi)部的元數(shù)據(jù)芦倒,以及用來防止由稀疏何異常大的記錄所導(dǎo)致的OOM錯(cuò)誤艺挪。
  • spark.memory.storageFraction表示Spark內(nèi)存區(qū)中存儲(chǔ)區(qū)所占的比例(默認(rèn)是0.5)。存儲(chǔ)區(qū)就是可以防止執(zhí)行功能搶占的內(nèi)存區(qū)兵扬。

spark.memory.fraction的值的設(shè)置應(yīng)該確保其占用的內(nèi)存能夠容納JVM堆內(nèi)存中老年代和永久代的大小麻裳。我們可以在下面的高級(jí)GC調(diào)整中進(jìn)行詳細(xì)討論

Determining Memory Consumption(確定內(nèi)存消耗)

最好的確定數(shù)據(jù)集內(nèi)存消耗情況的方法是創(chuàng)建一個(gè)RDD并將其緩存,然后通過Spark管理界面(Web UI)的存儲(chǔ)頁面去查看器钟。該頁面將會(huì)告訴你RDD占用的內(nèi)存大小津坑。
去估計(jì)一個(gè)特定對(duì)象的內(nèi)存消耗,可以使用SizeEstimator類的estimate方法傲霸。這個(gè)方法可以用來測(cè)試不同的數(shù)據(jù)布局對(duì)內(nèi)存的占用情況疆瑰,除此之外,也可以用來確定廣播變量對(duì)每一個(gè)執(zhí)行器的堆內(nèi)存的占用情況狞谱。

Tuning Data Structures(調(diào)整數(shù)據(jù)結(jié)構(gòu))

第一個(gè)降低內(nèi)存消耗的方法是避免由于Java的功能所過度使用的內(nèi)存乃摹,比如基于指針的數(shù)據(jù)結(jié)構(gòu)以及包裝類對(duì)象。下面有這幾種方法:

  1. 設(shè)計(jì)你自己的數(shù)據(jù)結(jié)構(gòu)代替Java或者Scala集合類來保存對(duì)象數(shù)組以及主要的數(shù)據(jù)類型(比如HashMap)跟衅,FastUtil 庫(kù)為主要數(shù)據(jù)類型提供了方便使用的集合類并且兼容Java的標(biāo)準(zhǔn)庫(kù)孵睬。
  2. 避免嵌套小對(duì)象或者指針的使用。
  3. 盡量用數(shù)字類型的鍵來代替字符類型的鍵
  4. 如果機(jī)器的內(nèi)存小于32GB伶跷,可以設(shè)置JVM的參數(shù)-XX:+UseCompressedOops用4個(gè)字節(jié)指針代替8個(gè)字節(jié)的指針掰读。你可以添加這些選項(xiàng)到spark-env.sh中。

Serialized RDD Storage(序列化RDD的存儲(chǔ))

盡管你做了這些調(diào)整叭莫,但是你的對(duì)象仍然太大蹈集,無法做到高效的存儲(chǔ),一個(gè)最簡(jiǎn)單的降低內(nèi)存使用的方法就是用序列化的形式存儲(chǔ)他們雇初,可以通過RDD persistence API中的序列化存儲(chǔ)級(jí)別來配置拢肆,例如MEMORY_ONLY_SER。一旦設(shè)置了序列化存儲(chǔ)級(jí)別靖诗,Spark就會(huì)將每一個(gè)RDD分區(qū)存儲(chǔ)成大的字節(jié)數(shù)組郭怪。這樣做的唯一劣勢(shì)就是會(huì)增加訪問時(shí)間,因?yàn)樵谑褂玫臅r(shí)候需要先進(jìn)行反序列化刊橘。如果你打算使用序列化的方式來緩存RDD鄙才,我們強(qiáng)烈建議使用Kryo,Kryo的序列化的結(jié)果遠(yuǎn)遠(yuǎn)小于Java的序列化機(jī)制促绵。

Garbage Collection Tuning(垃圾收集的調(diào)整)

當(dāng)你的程序中攒庵,在RDD的存儲(chǔ)方面嘴纺,有很多的打亂操作時(shí),JVM的垃圾收集將會(huì)成為一個(gè)問題浓冒。(如果你的程序只是讀取RDD一次然后在其上進(jìn)行一些操作栽渴,那么垃圾回收將不會(huì)成為一個(gè)問題)當(dāng)JVM需要回收舊的對(duì)象,為新的對(duì)象騰出空間時(shí)裆蒸,JVM需要掃描幾乎所有的Java對(duì)象然后發(fā)現(xiàn)不在使用的對(duì)象熔萧。主要的點(diǎn)就在于記住垃圾收集的開銷與Java對(duì)象的數(shù)量成正比,所以使用盡可能少的Java對(duì)象會(huì)大大降低垃圾收集的花費(fèi)僚祷。一個(gè)比較有效的方法就是用序列化的方式來緩存對(duì)象佛致,這樣就可以使用一個(gè)對(duì)象(字節(jié)數(shù)組)來存儲(chǔ)一個(gè)RDD分區(qū)。如果你的GC成為了一個(gè)問題辙谜,那么在嘗試其他技術(shù)之前俺榆,可以先嘗試serialized caching(序列化緩存)技術(shù)。

在另一種情況下装哆,GC也會(huì)成為一個(gè)問題罐脊,就是當(dāng)沒有足夠的內(nèi)存來執(zhí)行計(jì)算的時(shí)候,需要回收緩存RDD的內(nèi)存時(shí)蜕琴。下面我們將討論如何控制RDD內(nèi)存的分配來減少這種情況的發(fā)生萍桌。

Measuring the Impact of GC(評(píng)估GC的影響)

在調(diào)整GC的時(shí)候,第一步要做的就是統(tǒng)計(jì)收集GC發(fā)生的頻率和花費(fèi)的總時(shí)間凌简。我們可以通過設(shè)置-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStampsJvm參數(shù)來收集GC的的信息上炎。(可以通過configuration guide來查看如何在Spark作業(yè)中設(shè)置Java參數(shù))下次你的Spark作業(yè)在運(yùn)行的時(shí)候,你將會(huì)看到打印在工作節(jié)點(diǎn)線程中的GC發(fā)生的消息雏搂。注意藕施,這些日志會(huì)打印在你的Spark集群的工作節(jié)點(diǎn)上(在工作目錄的stdout文件上),而不是在你的驅(qū)動(dòng)程序那里凸郑。

Advanced GC Tuning(高級(jí)GC調(diào)整)

如果想要進(jìn)一步優(yōu)化GC裳食,我們首先得理解一些JVM內(nèi)存管理的基礎(chǔ)信息:

  • Java的堆內(nèi)存區(qū)分為新生代和老年代兩個(gè)部分。新生代用來保存短生命周期的對(duì)象芙沥,老年代用于存儲(chǔ)長(zhǎng)生命周期的對(duì)象诲祸。
  • 新生代進(jìn)一步分為三個(gè)區(qū)域:Eden(出生區(qū)),Survivor1(存活區(qū)1), Survivor2(存活區(qū)2)而昨。
  • 對(duì)垃圾收集的步驟做一個(gè)簡(jiǎn)單的描述:當(dāng)Eden區(qū)已滿救氯,會(huì)在Eden區(qū)進(jìn)行一次次級(jí)GC,將Eden和Survivor1區(qū)中仍然存活的對(duì)象復(fù)制到Survivor2區(qū)配紫。這些Survivor區(qū)域會(huì)發(fā)生交換径密。如果一個(gè)對(duì)象存活時(shí)間足夠長(zhǎng)或者Survivor2區(qū)已滿午阵,他將會(huì)被放入老年區(qū)躺孝。最后享扔,如果老年區(qū)接近滿了,一次完整的GC將被執(zhí)行植袍。

在Spark中GC優(yōu)化的目標(biāo)是確保只有長(zhǎng)時(shí)間存活的RDDs存儲(chǔ)在老年代中并且確保有充分的青年代空間存儲(chǔ)短生命周期對(duì)象惧眠。這樣可以避免需要通過完整的GC去收集一些任務(wù)執(zhí)行過程中創(chuàng)建的臨時(shí)對(duì)象。下面這些步驟應(yīng)該會(huì)有所幫助

  • 通過收集GC的狀態(tài)檢查是否發(fā)生了過多了垃圾收集于个。如果在一次任務(wù)結(jié)束前發(fā)生了多次的完整GC氛魁,這意味著對(duì)于所執(zhí)行的任務(wù)來說,并沒有足夠的可用內(nèi)存厅篓。
  • 如果發(fā)生了多次的Minor GC但是Major GC發(fā)生的次數(shù)卻不多秀存,這個(gè)時(shí)候可以通過為Eden區(qū)分配更多的空間來改善這種狀況。你可以為Eden區(qū)設(shè)置一個(gè)比較高的估值羽氮。如果Eden去的大小為E或链,你可以通過選項(xiàng)-Xmn=4/3*E來設(shè)置年輕代的大小。(通過4/3這個(gè)比例可以計(jì)算出survivor區(qū)域的大械笛骸)
  • 當(dāng)GC狀態(tài)被打印了出來澳盐,如果老年代接近滿,可以通過降低spark.memory.fraction的值降低緩存對(duì)內(nèi)存的使用量令宿;緩存較少的對(duì)象要好于減慢任務(wù)執(zhí)行的速度叼耙。當(dāng)然,我們也可以考慮減少年輕代的大小粒没。這意味給-Xmn選項(xiàng)設(shè)置一個(gè)較低的值筛婉。如果不想這樣做,可以嘗試更改JVM的NewRatio參數(shù)革娄。大多數(shù)JVM默認(rèn)的NewRatio參數(shù)值是2倾贰,這意味著老年代占用了2/3的堆內(nèi)存空間。這個(gè)比例超過了spark.memory.fraction拦惋,應(yīng)該足夠大了.
  • 可以通過-XX:+UseG1GC嘗試G1GC方法匆浙。在一些GC成為性能瓶頸的場(chǎng)景,使用G1垃圾收集器能夠提升性能厕妖。注意:如果堆內(nèi)存空間很大首尼,那么通過-XX:G1HeapRegionSize增加G1區(qū)域的大小就變的非常重要了。
  • 舉個(gè)例子言秸,如果的你的任務(wù)需要從HDFS中讀取數(shù)據(jù)软能,那么任務(wù)需要的內(nèi)存總數(shù)可以通過HDFS數(shù)據(jù)塊的大小進(jìn)行估算。注意:HDFS中的數(shù)據(jù)塊是經(jīng)過壓縮的举畸,所以讀入內(nèi)存后需要解壓查排,因此實(shí)際的大小是原來塊大小的2至3倍。如果我們需要能執(zhí)行3到4個(gè)任務(wù)的工作空間抄沮,并且HDFS的塊大小是128M跋核,所以我們估計(jì)Eden區(qū)的大小為43128岖瑰。
  • 監(jiān)控一下新的GC配置下,GC發(fā)生的時(shí)間和頻率砂代。

根據(jù)我們的經(jīng)驗(yàn)蹋订,最有效的GC優(yōu)化依賴你的應(yīng)用和可用的總內(nèi)存。在網(wǎng)上有更多關(guān)于GC優(yōu)化的描述刻伊,但是露戒,站在更高層次看,控制完整GC的發(fā)生頻率捶箱,能夠有效降低GC的開銷智什。

執(zhí)行器的GC優(yōu)化可以通過配置作業(yè)的spark.executor.extraJavaOptions來進(jìn)行。

Other Considerations(其他)

Level of Parallelism(并行度)

除非你為每一個(gè)操作設(shè)置了最高的并行度丁屎,否則不會(huì)利用集群中所有的結(jié)點(diǎn)撩鹿。Spark會(huì)根據(jù)map操作所處理的每一個(gè)文件的大小來自動(dòng)設(shè)置并行度(雖然你能夠通過可選的參數(shù)來控制他們比如SparkContext.textFile),對(duì)于那些分布式reduce操作悦屏,比如groupByKeyreduceByKey节沦,Spark會(huì)使用最大的上游RDD的分區(qū)數(shù)來確定并行度。當(dāng)然你可以通過將并行度作為第二個(gè)參數(shù)傳給相關(guān)的操作(可以查看 spark.PairRDDFunctions的文檔)础爬,或者設(shè)置spark.default.parallelism的值來改變默認(rèn)的并行度甫贯。一般而言,我們建議在集群中看蚜,每2或3個(gè)任務(wù)使用一個(gè)CPU核叫搁。

Memory Usage of Reduce Tasks(Reduce任務(wù)的內(nèi)存使用)

有些時(shí)候,你將會(huì)遇到OutOfMemoryError供炎,這并非因?yàn)槟愕腞DDs大小超過了可用內(nèi)存渴逻,而是因?yàn)槟愕娜蝿?wù)集合中的某一個(gè)任務(wù),比如groupByKey這樣的Reduce操作音诫,他太大了惨奕。Spark的混洗操作(sortByKeygroupByKey竭钝,reduceByKey等)會(huì)為每一個(gè)任務(wù)創(chuàng)建一個(gè)哈希表來執(zhí)行分組梨撞,這個(gè)哈希表通常會(huì)很大。最簡(jiǎn)單的解決此類錯(cuò)誤的方式就是提高并行度香罐,提高了并行度每一個(gè)該操作的任務(wù)的輸入集就會(huì)變小卧波。Spark可以有效的支持任務(wù)在200ms結(jié)束,因?yàn)樗诤芏嗟娜蝿?wù)之間重復(fù)使用了執(zhí)行器的JVM庇茫,并且有著較低的任務(wù)啟動(dòng)花費(fèi)港粱,所以你能夠安全的提升并行度的值,使其大于整個(gè)集群的內(nèi)核數(shù)旦签。

Broadcasting Large Variables(廣播大型變量)

使用 broadcast functionality能夠極大的減少每一次序列化任務(wù)使用的內(nèi)存大小查坪,以及在集群上啟動(dòng)一次作業(yè)的花費(fèi)锈颗。如果你的任務(wù)使用了來自于驅(qū)動(dòng)程序的大型對(duì)象,可以考慮使用廣播變量來調(diào)整他咪惠。Spark會(huì)將每一個(gè)任務(wù)序列化后的大小打印在Master上,所以你能夠看到并且決定你的任務(wù)是否過大淋淀;通常情況下遥昧,任務(wù)大于20KB就值的去進(jìn)行優(yōu)化。

Data Locality(數(shù)據(jù)局部性)

數(shù)據(jù)局部性對(duì)Spark作業(yè)的性能有著巨大的影響朵纷。如果數(shù)據(jù)和代碼在同一個(gè)結(jié)點(diǎn)上那么計(jì)算就會(huì)變的很快炭臭。但是如果代碼和數(shù)據(jù)是分開的,那么其中一個(gè)要移動(dòng)到另一個(gè)所在的結(jié)點(diǎn)袍辞。典型地鞋仍,移動(dòng)序列化后的代碼比移動(dòng)數(shù)據(jù)塊要快的多,這是因?yàn)榇a的大小遠(yuǎn)遠(yuǎn)小于數(shù)據(jù)塊的大小搅吁。Spark在調(diào)度作業(yè)的時(shí)候遵守?cái)?shù)據(jù)局部性的一般原則威创。

數(shù)據(jù)局部性表示數(shù)據(jù)與處理他的程序之間的距離。這里有幾種基于數(shù)據(jù)當(dāng)前位置的局部化的級(jí)別谎懦。順序是由近至遠(yuǎn):

  • PROCESS_LOCAL數(shù)據(jù)和處理程序在同一個(gè)JVM中肚豺,這是最好的情況
  • NODE_LOCAL數(shù)據(jù)和處理程序在同一個(gè)結(jié)點(diǎn)上。比如數(shù)據(jù)在HDFS的一個(gè)結(jié)點(diǎn)上界拦,同時(shí)一個(gè)執(zhí)行器也在同一個(gè)結(jié)點(diǎn)上吸申。這比PROCESS_LOCAL要慢一些,因?yàn)閿?shù)據(jù)要在進(jìn)程之間轉(zhuǎn)移
  • NO_PREF在任何地方訪問數(shù)據(jù)都是一樣的享甸,沒有任何局部性的優(yōu)先權(quán)
  • RACK_LOCAL數(shù)據(jù)和程序位于同一個(gè)機(jī)架上的不同機(jī)器上截碴,因此數(shù)據(jù)需要通過網(wǎng)絡(luò)進(jìn)行傳輸,典型地通過一個(gè)單開關(guān)
  • ANY數(shù)據(jù)可以在網(wǎng)絡(luò)中的任何位置蛉威,但與處理程序不在同一個(gè)機(jī)架上日丹。

Spark喜歡講所有任務(wù)安排到最好的局部性級(jí)別上,但是這并不總是可能的蚯嫌。在某些情況下聚凹,一些空閑的執(zhí)行器上沒有未處理的數(shù)據(jù)了,Spark會(huì)切換較低的局部性等級(jí)齐帚。這時(shí)候有兩個(gè)選項(xiàng):A)等待非空閑并且有未處理數(shù)據(jù)的執(zhí)行器上的繁忙的CPU空閑的時(shí)候妒牙,在數(shù)據(jù)所在的服務(wù)器上啟動(dòng)一個(gè)新的任務(wù),或者B)立刻在空閑的執(zhí)行上啟動(dòng)1個(gè)新的任務(wù)然后請(qǐng)求移動(dòng)數(shù)據(jù)对妄。

Spark會(huì)選擇哪一個(gè)呢湘今?Spark先選擇A選項(xiàng),等待繁忙的CPU一段期望的時(shí)間剪菱,如果這段時(shí)間后摩瞎,CPU仍然繁忙拴签,那么Spark就會(huì)選擇B選項(xiàng)。

這個(gè)在各個(gè)等級(jí)之間的期望時(shí)間可以分別單獨(dú)設(shè)置旗们,或者可以通過參數(shù)的形式整體來設(shè)置蚓哩;我們可以在configuration page上查看spark.locality參數(shù)的詳細(xì)信息。如果你的任務(wù)時(shí)間較長(zhǎng)或者局部化特性比較差上渴,你可以適當(dāng)?shù)卦龃筮@些配置的值岸梨,但是默認(rèn)值通常就夠用了。

Summary(總結(jié))

本文是一篇簡(jiǎn)短的指導(dǎo)稠氮,指出了當(dāng)你需要優(yōu)化Spark應(yīng)用時(shí)曹阔,你應(yīng)該關(guān)注哪些點(diǎn)。最重要的兩個(gè)點(diǎn)是數(shù)據(jù)序列化和內(nèi)存優(yōu)化隔披。對(duì)于大多數(shù)程序赃份,使用Kryo序列化以及在緩存數(shù)據(jù)的時(shí)候使用序列化形式將解決大部分常見的性能問題。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末奢米,一起剝皮案震驚了整個(gè)濱河市抓韩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鬓长,老刑警劉巖园蝠,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異痢士,居然都是意外死亡彪薛,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門怠蹂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來善延,“玉大人,你說我怎么就攤上這事城侧∫浊玻” “怎么了?”我有些...
    開封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵嫌佑,是天一觀的道長(zhǎng)豆茫。 經(jīng)常有香客問我,道長(zhǎng)屋摇,這世上最難降的妖魔是什么揩魂? 我笑而不...
    開封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮炮温,結(jié)果婚禮上火脉,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好倦挂,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開白布畸颅。 她就那樣靜靜地躺著,像睡著了一般方援。 火紅的嫁衣襯著肌膚如雪没炒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天犯戏,我揣著相機(jī)與錄音送火,去河邊找鬼。 笑死笛丙,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的假颇。 我是一名探鬼主播胚鸯,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼笨鸡!你這毒婦竟也來了姜钳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤形耗,失蹤者是張志新(化名)和其女友劉穎哥桥,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體激涤,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拟糕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了倦踢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片送滞。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖辱挥,靈堂內(nèi)的尸體忽然破棺而出犁嗅,到底是詐尸還是另有隱情,我是刑警寧澤晤碘,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布褂微,位于F島的核電站,受9級(jí)特大地震影響园爷,放射性物質(zhì)發(fā)生泄漏宠蚂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一童社、第九天 我趴在偏房一處隱蔽的房頂上張望肥矢。 院中可真熱鬧,春花似錦、人聲如沸甘改。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽十艾。三九已至抵代,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間忘嫉,已是汗流浹背荤牍。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留庆冕,地道東北人康吵。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像访递,于是被迫代替她去往敵國(guó)和親晦嵌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容