Spark權(quán)威指南(中文版)----第15章 Spark如何在集群環(huán)境運(yùn)行

Spark The Definitive Guide(Spark權(quán)威指南) 中文版。本書詳細(xì)介紹了Spark2.x版本的各個(gè)模塊饶套,目前市面上最好的Spark2.x學(xué)習(xí)書籍=嚷伞!啤覆!

關(guān)注:登峰大數(shù)據(jù),閱讀中文Spark權(quán)威指南(完整版)惭聂,系統(tǒng)學(xué)習(xí)Spark大數(shù)據(jù)框架窗声!

到目前為止,在本書中辜纲,我們主要關(guān)注Spark作為編程接口的特性笨觅。我們已經(jīng)討論了結(jié)構(gòu)化api如何接受邏輯操作,將其分解為邏輯計(jì)劃耕腾,并將其轉(zhuǎn)換為物理計(jì)劃见剩,該物理計(jì)劃實(shí)際上由跨機(jī)器集群執(zhí)行的彈性分布式數(shù)據(jù)集(RDD)操作組成。本章主要討論Spark執(zhí)行代碼時(shí)會(huì)發(fā)生什么扫俺。我們以一種與實(shí)現(xiàn)無關(guān)的方式討論這個(gè)問題----這既不依賴于您正在使用的集群管理器苍苞,也不依賴于您正在運(yùn)行的代碼。最終牵舵,所有Spark代碼以相同的方式運(yùn)行柒啤。

本章涵蓋了幾個(gè)關(guān)鍵的主題:

Spark應(yīng)用程序的體系結(jié)構(gòu)和組件

Spark應(yīng)用程序在Spark內(nèi)外的生命周期

重要的底層執(zhí)行屬性倦挂,如pipelining

運(yùn)行一個(gè)Spark應(yīng)用程序需要什么。

讓我們從體系結(jié)構(gòu)開始担巩。

? ? ? 15.1.???Spark應(yīng)用程序的體系結(jié)構(gòu)

在第2章中方援,我們討論了Spark應(yīng)用程序的一些高級(jí)組件。讓我們再復(fù)習(xí)一遍:

Spark Driver:

Driver程序是您的Spark應(yīng)用程序的“駕駛座”中的進(jìn)程涛癌。它是Spark應(yīng)用程序執(zhí)行的控制器犯戏,維護(hù)Spark集群的所有狀態(tài)(執(zhí)行器的狀態(tài)和其上運(yùn)行的任務(wù))。其必須與集群管理器接口配合拳话,以獲得可用的物理資源先匪,并運(yùn)行executors。最終弃衍,這只是一個(gè)物理機(jī)器上的進(jìn)程呀非,負(fù)責(zé)維護(hù)集群上運(yùn)行的應(yīng)用程序的狀態(tài)。

Spark?executors:

Spark?executor是執(zhí)行Spark ?driver程序分配的任務(wù)的進(jìn)程镜盯。executor有一個(gè)核心職責(zé):接受driver程序分配的任務(wù)岸裙,運(yùn)行它們,并報(bào)告它們的狀態(tài)(成功或失敗)和結(jié)果給driver速缆。每個(gè)Spark應(yīng)用程序都有自己獨(dú)立的executor進(jìn)程降允。

Cluster Manager集群管理器:

Spark Driver程序和Executor不會(huì)脫離Spark應(yīng)用程序而存在,這就是集群管理器的作用所在艺糜。集群管理器負(fù)責(zé)維護(hù)運(yùn)行Spark應(yīng)用程序的集群剧董。有點(diǎn)令人困惑的是,集群管理器有自己的“Driver程序”(有時(shí)稱為master)和“worker”抽象破停。其核心區(qū)別在于翅楼,它們與物理機(jī)器相關(guān)聯(lián),而不是與進(jìn)程相關(guān)聯(lián)(如Spark中的進(jìn)程)辱挥。圖15-1顯示了一個(gè)基本的集群設(shè)置犁嗅。圖左邊的機(jī)器是集群管理器driver程序節(jié)點(diǎn)。圓圈表示運(yùn)行在每個(gè)工作節(jié)點(diǎn)上并管理每個(gè)工作節(jié)點(diǎn)的守護(hù)進(jìn)程晤碘。到目前為止還沒有運(yùn)行Spark應(yīng)用程序—這些只是來自集群管理器的進(jìn)程。

當(dāng)實(shí)際運(yùn)行Spark應(yīng)用程序時(shí)功蜓,我們從集群管理器請求資源來運(yùn)行它园爷。根據(jù)應(yīng)用程序的配置方式,這可以包括一個(gè)運(yùn)行Spark driver程序的資源式撼,也可以只是Spark應(yīng)用程序執(zhí)行器的資源童社。在Spark應(yīng)用程序執(zhí)行過程中,集群管理器將負(fù)責(zé)管理運(yùn)行應(yīng)用程序的底層機(jī)器著隆。

Spark目前支持三個(gè)集群管理器:一個(gè)簡單的內(nèi)置standalone集群管理器扰楼、Apache Mesos和Hadoop Yarn呀癣。但是,這個(gè)列表將繼續(xù)增長弦赖,所以一定要檢查您最喜歡的集群管理器的文檔(譯者注:目前已經(jīng)支持第四個(gè)集群管理器:Kubernetes)项栏。

現(xiàn)在我們已經(jīng)介紹了應(yīng)用程序的基本組件,讓我們來看看運(yùn)行應(yīng)用程序時(shí)需要做的第一項(xiàng)選擇:選擇執(zhí)行模式蹬竖。

15.1.1.?? 執(zhí)行模式

執(zhí)行模式使您能夠在運(yùn)行應(yīng)用程序時(shí)確定上述資源的物理位置沼沈。您有三種模式可供選擇:

Cluster mode

Client mode

Local mode

我們將使用圖15-1作為模板,詳細(xì)介紹其中的每一個(gè)币厕。在下一節(jié)中列另,帶實(shí)邊框的矩形表示Spark Driver程序進(jìn)程,而帶點(diǎn)邊框的矩形表示executor進(jìn)程旦装。

Cluster mode

集群模式可能是運(yùn)行Spark應(yīng)用程序的最常見方式页衙。在集群模式下,用戶向集群管理器提交預(yù)編譯的JAR阴绢、Python腳本或R腳本拷姿。然后,集群管理器在集群內(nèi)的worker節(jié)點(diǎn)上啟動(dòng)driver程序進(jìn)程旱函,以及executor進(jìn)程响巢。這意味著集群管理器負(fù)責(zé)維護(hù)所有與Spark應(yīng)用程序相關(guān)的進(jìn)程。圖15-2顯示集群管理器將我們的driver程序放在一個(gè)worker節(jié)點(diǎn)上棒妨,將executor放在其他worker節(jié)點(diǎn)上踪古。

Client mode

client模式幾乎與集群模式相同,只是Spark driver程序仍然位于提交應(yīng)用程序的客戶機(jī)上券腔。這意味著客戶機(jī)負(fù)責(zé)維護(hù)Spark Driver程序進(jìn)程伏穆,集群管理器負(fù)責(zé)維護(hù)executor進(jìn)程。在圖15-3中纷纫,我們在一臺(tái)集群外的機(jī)器上運(yùn)行Spark應(yīng)用程序枕扫。這些機(jī)器通常稱為網(wǎng)關(guān)機(jī)器或邊緣節(jié)點(diǎn)。在圖15-3中辱魁,您可以看到Driver程序運(yùn)行在集群外部的機(jī)器上烟瞧,但是worker位于集群中的機(jī)器上。

Local mode

Local模式與前兩種模式有很大的不同:它在一臺(tái)機(jī)器上運(yùn)行整個(gè)Spark應(yīng)用程序染簇。它通過單臺(tái)機(jī)器上的線程實(shí)現(xiàn)并行参滴。這是學(xué)習(xí)Spark、測試應(yīng)用程序或使用本地開發(fā)進(jìn)行迭代試驗(yàn)的常見方法锻弓。但是砾赔,我們不建議使用本地模式來運(yùn)行生產(chǎn)應(yīng)用程序。

15.2.???Spark應(yīng)用程序的生命周期

到目前為止,本章已經(jīng)涵蓋了討論Spark應(yīng)用程序所需的詞匯表”┬模現(xiàn)在是時(shí)候從實(shí)際Spark代碼的“外部”討論Spark應(yīng)用程序的整個(gè)生命周期了妓盲。我們將通過一個(gè)使用spark-submit(在第3章中介紹)運(yùn)行應(yīng)用程序的示例來實(shí)現(xiàn)這一點(diǎn)。我們假設(shè)一個(gè)集群已經(jīng)運(yùn)行了四個(gè)節(jié)點(diǎn)专普,一個(gè)Driver程序(不是Spark Driver程序悯衬,而是集群管理器Driver程序)和三個(gè)worker節(jié)點(diǎn)。此時(shí)脆诉,實(shí)際的集群管理器我們并不關(guān)注:本節(jié)使用前一節(jié)中的詞匯表逐步介紹Spark應(yīng)用程序的生命周期甚亭,從初始化到程序退出。

提示本節(jié)還使用了插圖击胜,并遵循我們前面介紹的相同符號(hào)亏狰。此外,我們現(xiàn)在介紹表示網(wǎng)絡(luò)通信的標(biāo)線偶摔。較暗的箭頭表示由Spark或與Spark相關(guān)的進(jìn)程相關(guān)的通信暇唾,而虛線表示更一般的通信(如集群管理通信)。

15.2.1.?? Client Request

第一步是提交一個(gè)實(shí)際的應(yīng)用程序辰斋。這將是一個(gè)預(yù)編譯的JAR或庫策州。此時(shí),您正在本地機(jī)器上執(zhí)行代碼宫仗,并將向集群管理器Driver程序節(jié)點(diǎn)發(fā)出請求(圖15-4)够挂。這里,我們明確地要求僅為Spark Driver程序進(jìn)程提供資源藕夫。我們假設(shè)集群管理器接受這個(gè)提議孽糖,并將Driver放在集群中的一個(gè)節(jié)點(diǎn)上。提交原始作業(yè)的客戶機(jī)進(jìn)程退出毅贮,應(yīng)用程序開始在集群上運(yùn)行办悟。

要做到這一點(diǎn),需要在終端上運(yùn)行如下命令:

15.2.2.?? Launch運(yùn)行

現(xiàn)在驅(qū)動(dòng)程序進(jìn)程已經(jīng)放在集群上滩褥,它開始運(yùn)行用戶代碼(圖15-5)病蛉。這段代碼必須包含一個(gè)初始化Spark集群(例如,driver + executor)的SparkSession瑰煎。SparkSession隨后將與集群管理器通信(深色線)铺然,要求它在集群中啟動(dòng)Spark executor進(jìn)程(淺色線)。executor的數(shù)量及其相關(guān)配置由用戶通過原始spark-submit調(diào)用中的命令行參數(shù)設(shè)置丢间。

集群管理器的響應(yīng)是啟動(dòng)執(zhí)行器進(jìn)程(假設(shè)一切正常)探熔,并將有關(guān)它們位置的相關(guān)信息發(fā)送給Driver進(jìn)程。在所有東西都正確地連接起來之后烘挫,我們有了一個(gè)“Spark Cluster”,正如您今天可能認(rèn)為的那樣。

15.2.3.?? Execution執(zhí)行

現(xiàn)在我們有了一個(gè)“Spark集群”饮六,Spark以其愉快的方式執(zhí)行代碼其垄,如圖15-6所示。Driver和worker彼此通信卤橄,執(zhí)行代碼并移動(dòng)數(shù)據(jù)绿满。Driver將任務(wù)調(diào)度到每個(gè)worker上,每個(gè)worker用這些任務(wù)的狀態(tài)和成功或失敗來響應(yīng)窟扑。(我們將很快介紹這些細(xì)節(jié)喇颁。)

15.2.4.?? Completion完成

在Spark應(yīng)用程序完成后,Driver進(jìn)程退出嚎货,成功或失敗(圖15-7)橘霎。然后集群管理器為Driver關(guān)閉Spark集群中的Executor。此時(shí)殖属,您可以通過向集群管理器詢問此信息來查看Spark應(yīng)用程序的成功或失敗姐叁。

15.3.???Spark應(yīng)用程序的生命周期(insidespark)

我們剛剛研究了用戶代碼之外的Spark應(yīng)用程序的生命周期(基本上是支持Spark的基礎(chǔ)設(shè)施),但是更重要的是討論在運(yùn)行應(yīng)用程序時(shí)在Spark中發(fā)生了什么洗显。這是“用戶代碼”(定義Spark應(yīng)用程序的實(shí)際代碼)外潜。每個(gè)應(yīng)用程序由一個(gè)或多個(gè)Spark作業(yè)組成。應(yīng)用程序中的Spark作業(yè)是串行執(zhí)行的(除非使用線程并行啟動(dòng)多個(gè)操作)挠唆。

15.3.1.?? SparkSession

任何Spark應(yīng)用程序的第一步都是創(chuàng)建一個(gè)SparkSession处窥。在許多交互模式中,默認(rèn)會(huì)為你創(chuàng)建這樣一個(gè)對象玄组,但在應(yīng)用程序中滔驾,您必須手動(dòng)完成對象的創(chuàng)建。您的一些遺留代碼可能使用new SparkContext模式巧勤。應(yīng)該避免這種情況嵌灰,采用SparkSession上的builder方法,它更健壯地實(shí)例化Spark和SQL上下文颅悉,并確保沒有上下文沖突沽瞭,因?yàn)榭赡苡卸鄠€(gè)庫試圖在同一個(gè)Spark應(yīng)用程序中創(chuàng)建會(huì)話:

在您擁有一個(gè)SparkSession之后,您應(yīng)該能夠運(yùn)行您的Spark代碼剩瓶。從SparkSession中驹溃,您還可以相應(yīng)地訪問所有底層和遺留上下文和配置。注意延曙,SparkSession類只是在Spark 2.X中添加的豌鹤。您可能發(fā)現(xiàn)的舊代碼將直接為結(jié)構(gòu)化api創(chuàng)建SparkContext和SQLContext。

SparkContext

SparkSession中的SparkContext對象表示到Spark集群的連接枝缔。這個(gè)類是您與Spark的一些低層api(如RDDs)通信的方式布疙。在舊的示例和文檔中蚊惯,它通常存儲(chǔ)為變量sc。通過SparkContext灵临,您可以創(chuàng)建RDDs截型、累加器和廣播變量,并且可以在集群上運(yùn)行代碼儒溉。

在大多數(shù)情況下宦焦,不需要顯式地初始化SparkContext;您應(yīng)該能夠通過SparkSession訪問它。如果你想顿涣,你應(yīng)該用最通用的方法創(chuàng)建它波闹,通過getOrCreate方法:

SparkSession,SQLContext, 和HiveContext在Spark的早期版本中,SQLContext和HiveContext提供了處理DataFrames和SparkSQL的能力涛碑,并且通常在示例精堕、文檔和遺留代碼中作為變量sqlContext存儲(chǔ)。作為一個(gè)歷史點(diǎn)锌唾,Spark1.X實(shí)際上有兩個(gè)上下文:SparkContext和SQLContext锄码。這兩個(gè)上下文的表現(xiàn)各不相同。前者側(cè)重于對Spark的核心抽象進(jìn)行更細(xì)粒度的控制晌涕,而后者側(cè)重于像SparkSQL這樣的高級(jí)工具滋捶。在Spark2.0中,開源社區(qū)將這兩個(gè)api合并到我們今天使用的集中式SparkSession中余黎。但是重窟,這兩個(gè)api仍然存在,您可以通過SparkSession訪問它們惧财。需要注意的是巡扇,您不應(yīng)該使用SQLContext,也很少需要使用SparkContext垮衷。

初始化SparkSession之后厅翔,就可以執(zhí)行一些代碼了。正如我們在前幾章中所知道的搀突,所有Spark代碼都編譯為RDDs刀闷。因此,在下一節(jié)中仰迁,我們將使用一些邏輯說明(DataFrame作業(yè))甸昏,并逐步了解隨著時(shí)間的推移會(huì)發(fā)生什么。

15.3.2.?Logical Instructions邏輯指令

正如您在本書的開頭所看到的徐许,Spark代碼本質(zhì)上由Transformation和action組成施蜜。如何構(gòu)建這些取決于您——無論是通過SQL、低層RDD操作雌隅,還是機(jī)器學(xué)習(xí)算法翻默。理解我們?nèi)绾问褂孟馜ataFrames這樣的聲明性指令缸沃,并將它們轉(zhuǎn)換為物理執(zhí)行計(jì)劃,這是理解Spark如何在集群上運(yùn)行的一個(gè)重要步驟冰蘑。在本節(jié)中和泌,請確保在一個(gè)新的環(huán)境(一個(gè)新的Spark shell)中運(yùn)行此操作村缸,以跟蹤job祠肥、stage和task編號(hào)。

邏輯指令到物理執(zhí)行

我們在第2部分中提到了這一點(diǎn)梯皿,但是值得重申一遍仇箱,以便更好地理解Spark如何獲取代碼并在集群上實(shí)際運(yùn)行命令。我們將逐行介紹更多的代碼东羹,解釋幕后發(fā)生的事情剂桥,以便您能夠更好地理解Spark應(yīng)用程序。在后面的章節(jié)中属提,當(dāng)我們討論監(jiān)控权逗,我們將通過Spark UI對Spark作業(yè)執(zhí)行更詳細(xì)的跟蹤。在當(dāng)前的示例中冤议,我們將采用更簡單的方法斟薇。我們將做一個(gè)包含三個(gè)步驟的job:使用一個(gè)簡單的DataFrame,我們將對它進(jìn)行重新分區(qū)恕酸,執(zhí)行一個(gè)值對一個(gè)值的操作堪滨,然后聚合一些值并收集最終結(jié)果。

提示這段代碼是用PythonSpark2.2編寫并運(yùn)行的(您將在Scala中得到相同的結(jié)果蕊温,因此我們省略了它)袱箱。作業(yè)的數(shù)量不太可能發(fā)生巨大的變化,但是Spark的底層優(yōu)化可能會(huì)得到改進(jìn)义矛,從而改變物理執(zhí)行策略发笔。

當(dāng)運(yùn)行這段代碼時(shí),我們可以看到您的操作觸發(fā)了一個(gè)完整的Spark作業(yè)凉翻。讓我們來看看explain計(jì)劃了讨,以鞏固我們對物理執(zhí)行計(jì)劃的理解。我們可以在Spark UI中的SQL選項(xiàng)卡(在實(shí)際運(yùn)行查詢之后)訪問這些信息噪矛,以及:

當(dāng)您調(diào)用collect(或任何action)時(shí)量蕊,您所擁有的是Spark作業(yè)的執(zhí)行,該作業(yè)由各個(gè)stages和tasks組成艇挨。如果您正在本地機(jī)器上運(yùn)行此命令残炮,請轉(zhuǎn)到localhost:4040查看Spark UI。我們將跟隨“jobs”選項(xiàng)卡缩滨,隨著我們進(jìn)一步深入細(xì)節(jié)势就,最終跳轉(zhuǎn)到各個(gè)stages和tasks泉瞻。

15.3.3.?? A Spark Job

一般來說,一個(gè)action操作出發(fā)一個(gè)spark job苞冯。Action操作總是返回一個(gè)結(jié)果值袖牙。每個(gè)job可以包含多個(gè)stages,stages的個(gè)數(shù)多少舅锄,有shuffle操作的transformation決定鞭达。

這項(xiàng)job分為以下幾個(gè)stages和tasks:

我希望您至少對我們?nèi)绾蔚玫竭@些數(shù)字有些困惑,以便我們能夠花時(shí)間更好地理解發(fā)生了什么!

15.3.4.?? Stages

Spark中的stages表示可以一起執(zhí)行的任務(wù)組皇忿,以便在多臺(tái)機(jī)器上計(jì)算相同的操作畴蹭。一般來說,Spark會(huì)嘗試打包盡可能多的工作(如:盡可能多的transformation操作)到同一個(gè)stage鳍烁,但是Spark引擎在shuffle操作之后產(chǎn)生新的stage叨襟。shuffle表示數(shù)據(jù)的物理重新分區(qū)——例如,對DataFrame進(jìn)行排序幔荒,或按key對從文件中加載的數(shù)據(jù)進(jìn)行分組(這需要將具有相同key的記錄發(fā)送到相同節(jié)點(diǎn))糊闽。這種類型的重新分區(qū)需要跨Executor協(xié)調(diào)來移動(dòng)數(shù)據(jù)。Spark在每次shuffle之后啟動(dòng)一個(gè)新stage爹梁,并跟蹤各個(gè)stage必須以什么順序運(yùn)行才能計(jì)算最終結(jié)果右犹。

在我們前面看到的job中,前兩個(gè)stages對應(yīng)于創(chuàng)建DataFrames所執(zhí)行的rang()方法卫键。默認(rèn)情況下傀履,當(dāng)您使用rang()創(chuàng)建一個(gè)DataFrame時(shí),它有八個(gè)分區(qū)莉炉。下一步是重新分區(qū)钓账。這通過shuffle數(shù)據(jù)來改變分區(qū)的數(shù)量。這些DataFrames被劃分為6個(gè)分區(qū)和5個(gè)分區(qū)絮宁,對應(yīng)于stage3和stages4中的task數(shù)量梆暮。

stage3和stage4對每個(gè)DataFrame執(zhí)行操作,stage的末尾表示join(shuffle)绍昂。突然啦粹,我們有200個(gè)任務(wù)。這是因?yàn)閟park.sql.shuffle.partitions配置的默認(rèn)值為200窘游,這意味著在執(zhí)行過程中執(zhí)行shuffle時(shí)唠椭,默認(rèn)情況下輸出200個(gè)洗牌分區(qū)。您可以更改此值忍饰,并且輸出分區(qū)的數(shù)量也將發(fā)生更改贪嫂。

提示我們將在第19章更詳細(xì)地討論分區(qū)的數(shù)量,因?yàn)樗且粋€(gè)非常重要的參數(shù)艾蓝。應(yīng)該根據(jù)集群中的內(nèi)核數(shù)量設(shè)置此值力崇,以確保高效執(zhí)行斗塘。下面是設(shè)置方法:spark.conf.set("spark.sql.shuffle.partitions",?50)

一個(gè)好的經(jīng)驗(yàn)法則是分區(qū)的數(shù)量應(yīng)該大于集群中executor的數(shù)量,這可能是由多個(gè)因素造成的亮靴,具體取決于工作負(fù)載馍盟。如果您在本地機(jī)器上運(yùn)行代碼,您應(yīng)該將該值設(shè)置得更低茧吊,因?yàn)楸镜貦C(jī)器不太可能并行執(zhí)行那么多任務(wù)贞岭。對于一個(gè)集群,這更像是一個(gè)默認(rèn)值饱狂,其中可能有更多的executors cores可供使用曹步。無論分區(qū)的數(shù)量如何,整個(gè)stage都是并行計(jì)算的休讳。最終的結(jié)果將單獨(dú)地聚合這些分區(qū),在最終將最終結(jié)果發(fā)送到Driver之前尿孔,將它們都放到一個(gè)單獨(dú)的分區(qū)中俊柔。在本書的這一部分中,我們將多次看到這種配置活合。

15.3.5.??Tasks

Spark中的stage由task組成雏婶。每個(gè)task對應(yīng)于將在單個(gè)executor上運(yùn)行的數(shù)據(jù)塊和一組transformation的組合。如果數(shù)據(jù)集中有一個(gè)大分區(qū)白指,我們將有一個(gè)任務(wù)留晚。如果有1000個(gè)小分區(qū),那么就有1000個(gè)任務(wù)可以并行執(zhí)行告嘲。task只是應(yīng)用于數(shù)據(jù)單元(分區(qū))的計(jì)算單元错维。將數(shù)據(jù)劃分為更多的分區(qū)意味著可以并行執(zhí)行更多的分區(qū)。這不是萬靈藥橄唬,但它是一個(gè)開始優(yōu)化的簡單地方赋焕。

15.4.???執(zhí)行細(xì)節(jié)

在我們結(jié)束本章之前,Spark中的task和stage有一些重要的特性值得回顧仰楚。首先隆判,Spark自動(dòng)將可以一起完成的task和stage串聯(lián)起來,比如一個(gè)map操作后面跟著另一個(gè)map操作僧界。其次侨嘀,對于所有的shuffle操作,Spark將數(shù)據(jù)寫入穩(wěn)定的存儲(chǔ)(例如磁盤)捂襟,并可以在多個(gè)作業(yè)之間重用數(shù)據(jù)咬腕。我們將依次討論這些概念,因?yàn)樗鼈儗⒃谀_始通過Spark UI檢查應(yīng)用程序時(shí)出現(xiàn)笆豁。

15.4.1.?? Pipelining

Spark之所以成為“內(nèi)存計(jì)算框架”的一個(gè)重要原因是郎汪,與之前的框架(例如MapReduce)不同赤赊,Spark在將數(shù)據(jù)寫入內(nèi)存或磁盤之前,會(huì)在某個(gè)時(shí)間點(diǎn)執(zhí)行盡可能多的步驟煞赢。Spark執(zhí)行的一個(gè)關(guān)鍵優(yōu)化是pipelining抛计,它發(fā)生在RDD級(jí)別或以下。使用pipelining照筑,任何直接相互提供數(shù)據(jù)的操作序列(不需要在節(jié)點(diǎn)之間移動(dòng)數(shù)據(jù))都被分解為一個(gè)單獨(dú)的任務(wù)階段吹截,這些任務(wù)一起完成所有的操作。例如,如果您編寫一個(gè)RDD-based程序,包括一個(gè)map,一個(gè)filter,然后另一個(gè)map,這些任務(wù)將存在于一個(gè)stage中凝危,讀取每個(gè)輸入數(shù)據(jù)記錄,然后傳輸數(shù)據(jù)到第一個(gè)map,然后數(shù)據(jù)通過filter,如果需要通過最后一個(gè)map函數(shù)波俄。這種流水線版本的計(jì)算比在每一步之后將中間結(jié)果寫入內(nèi)存或磁盤要快得多。對于執(zhí)行select蛾默、filter和select的DataFrame或SQL計(jì)算懦铺,也會(huì)發(fā)生類似的pipelining操作。

從實(shí)用的角度來看,pipelining對用戶是透明的,你寫一個(gè)應(yīng)用支鸡,運(yùn)行時(shí)將自動(dòng)運(yùn)行pipelining,但是你會(huì)發(fā)現(xiàn)如果你檢查您的應(yīng)用程序通過SparkUI或通過其日志文件,你會(huì)看到多個(gè)RDD或DataFrame操作被安排成一個(gè)單一的Stage冬念。

15.4.2.??ShufflePersistence

有時(shí)會(huì)看到的第二個(gè)屬性是shuffle持久性。當(dāng)Spark需要運(yùn)行一個(gè)必須跨節(jié)點(diǎn)移動(dòng)數(shù)據(jù)的操作時(shí)牧挣,例如reduce-by-key操作(每個(gè)key的輸入數(shù)據(jù)首先需要從多個(gè)節(jié)點(diǎn)收集到一起)急前,此時(shí)Spark引擎就不能再執(zhí)行流水線,而是執(zhí)行跨網(wǎng)絡(luò)shuffle瀑构。Spark總是通過在執(zhí)行階段首先讓“源”任務(wù)(發(fā)送數(shù)據(jù)的任務(wù))將shuffle文件寫入本地磁盤來執(zhí)行shuffle裆针。然后,進(jìn)行分組和合并數(shù)據(jù)的stage啟動(dòng)并運(yùn)行任務(wù)寺晌,這些任務(wù)從每個(gè)shuffle文件中獲取相應(yīng)的記錄并執(zhí)行計(jì)算(例如世吨,獲取和處理特定范圍的key的數(shù)據(jù))。將shuffle文件保存到磁盤中折剃,可以讓Spark在比源階段更晚的時(shí)間運(yùn)行這個(gè)階段(例如另假,如果沒有足夠的執(zhí)行者同時(shí)運(yùn)行這兩個(gè)階段),還可以讓引擎在失敗時(shí)重新啟動(dòng)reduce任務(wù)怕犁,而無需重新運(yùn)行所有輸入任務(wù)边篮。

對于shuffle持久性,您將看到的一個(gè)副作用是奏甫,在已經(jīng)shuffle的數(shù)據(jù)上運(yùn)行一個(gè)新作業(yè)不會(huì)重新運(yùn)行shuffle的“源”端戈轿。因?yàn)閟huffle文件已經(jīng)在更早的時(shí)候被寫到磁盤上,Spark知道它可以使用它們來運(yùn)行任務(wù)的后期阵子,并且它不需要重做早期的那些思杯。在Spark UI和日志中,您將看到預(yù)shuffle階段標(biāo)記為“跳過”。這種自動(dòng)優(yōu)化可以在對相同數(shù)據(jù)運(yùn)行多個(gè)作業(yè)的工作負(fù)載中節(jié)省時(shí)間色乾,但是當(dāng)然誊册,為了獲得更好的性能,您可以使用DataFrame或RDD緩存方法執(zhí)行自己的緩存暖璧,該方法允許您精確地控制保存哪些數(shù)據(jù)以及保存在何處案怯。在對聚合數(shù)據(jù)運(yùn)行一些Spark操作并在UI中檢查它們之后,您將很快習(xí)慣這種行為澎办。

15.5.? 結(jié)束語

在本章中嘲碱,我們討論了在集群上執(zhí)行應(yīng)用程序時(shí),會(huì)發(fā)生什么情況局蚀。這意味著集群將如何實(shí)際運(yùn)行代碼麦锯,以及在此過程中在Spark應(yīng)用程序中發(fā)生了什么。此時(shí)琅绅,您應(yīng)該很容易理解Spark應(yīng)用程序內(nèi)外發(fā)生了什么扶欣。這將為調(diào)試應(yīng)用程序提供一個(gè)起點(diǎn)。第16章將討論編寫Spark應(yīng)用程序以及在編寫時(shí)應(yīng)該考慮的事項(xiàng)奉件。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末宵蛀,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子县貌,更是在濱河造成了極大的恐慌,老刑警劉巖凑懂,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件煤痕,死亡現(xiàn)場離奇詭異,居然都是意外死亡接谨,警方通過查閱死者的電腦和手機(jī)摆碉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來脓豪,“玉大人巷帝,你說我怎么就攤上這事∩ㄒ梗” “怎么了楞泼?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長笤闯。 經(jīng)常有香客問我堕阔,道長,這世上最難降的妖魔是什么颗味? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任超陆,我火速辦了婚禮,結(jié)果婚禮上浦马,老公的妹妹穿的比我還像新娘时呀。我一直安慰自己张漂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布谨娜。 她就那樣靜靜地躺著航攒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瞧预。 梳的紋絲不亂的頭發(fā)上屎债,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天,我揣著相機(jī)與錄音垢油,去河邊找鬼盆驹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛滩愁,可吹牛的內(nèi)容都是我干的躯喇。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼硝枉,長吁一口氣:“原來是場噩夢啊……” “哼廉丽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起妻味,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤正压,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后责球,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體焦履,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年雏逾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嘉裤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,992評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡栖博,死狀恐怖屑宠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仇让,我是刑警寧澤典奉,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站妹孙,受9級(jí)特大地震影響总珠,放射性物質(zhì)發(fā)生泄漏睦授。R本人自食惡果不足惜志电,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一彻消、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦笨触、人聲如沸懦傍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽粗俱。三九已至,卻和暖如春虚吟,著一層夾襖步出監(jiān)牢的瞬間寸认,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工串慰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留偏塞,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓邦鲫,卻偏偏與公主長得像灸叼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子庆捺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評論 2 355

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