我們可以發(fā)現(xiàn),Spark 應(yīng)用程序在提交執(zhí)行后,控制臺(tái)會(huì)打印很多日志信息,這些信息看起來(lái)是雜亂無(wú)章的,但是卻在一定程度上體現(xiàn)了一個(gè)被提交的 Spark job 在集群中是如何被調(diào)度執(zhí)行的,那么在這一節(jié),將會(huì)向大家介紹一個(gè)典型的 Spark job 是如何被調(diào)度執(zhí)行的。
我們先來(lái)了解以下幾個(gè)概念:
DAG: 即 Directed Acyclic Graph,有向無(wú)環(huán)圖,這是一個(gè)圖論中的概念。如果一個(gè)有向圖無(wú)法從某個(gè)頂點(diǎn)出發(fā)經(jīng)過(guò)若干條邊回到該點(diǎn),則這個(gè)圖是一個(gè)有向無(wú)環(huán)圖。
Job:我們知道,Spark 的計(jì)算操作是 lazy 執(zhí)行的,只有當(dāng)碰到一個(gè)動(dòng)作 (Action) 算子時(shí)才會(huì)觸發(fā)真正的計(jì)算。一個(gè) Job 就是由動(dòng)作算子而產(chǎn)生包含一個(gè)或多個(gè) Stage 的計(jì)算作業(yè)。
Stage:Job 被確定后,Spark 的調(diào)度器 (DAGScheduler) 會(huì)根據(jù)該計(jì)算作業(yè)的計(jì)算步驟把作業(yè)劃分成一個(gè)或者多個(gè) Stage。Stage 又分為 ShuffleMapStage 和 ResultStage,前者以 shuffle 為輸出邊界,后者會(huì)直接輸出結(jié)果,其邊界可以是獲取外部數(shù)據(jù),也可以是以一個(gè) ShuffleMapStage 的輸出為邊界。每一個(gè) Stage 將包含一個(gè) TaskSet。
TaskSet:?代表一組相關(guān)聯(lián)的沒(méi)有 shuffle 依賴關(guān)系的任務(wù)組成任務(wù)集。一組任務(wù)會(huì)被一起提交到更加底層的 TaskScheduler。
Task:代表單個(gè)數(shù)據(jù)分區(qū)上的最小處理單元。分為 ShuffleMapTask 和 ResultTask。ShuffleMapTask 執(zhí)行任務(wù)并把任務(wù)的輸出劃分到 (基于 task 的對(duì)應(yīng)的數(shù)據(jù)分區(qū)) 多個(gè) bucket(ArrayBuffer) 中,ResultTask 執(zhí)行任務(wù)并把任務(wù)的輸出發(fā)送給驅(qū)動(dòng)程序。
Spark 的作業(yè)任務(wù)調(diào)度是復(fù)雜的,需要結(jié)合源碼來(lái)進(jìn)行較為詳盡的分析,但是這已經(jīng)超過(guò)本文的范圍,所以這一節(jié)我們只是對(duì)大致的流程進(jìn)行分析。
Spark 應(yīng)用程序被提交后,當(dāng)某個(gè)動(dòng)作算子觸發(fā)了計(jì)算操作時(shí),SparkContext 會(huì)向 DAGScheduler 提交一個(gè)作業(yè),接著 DAGScheduler 會(huì)根據(jù) RDD 生成的依賴關(guān)系劃分 Stage,并決定各個(gè) Stage 之間的依賴關(guān)系,Stage 之間的依賴關(guān)系就形成了 DAG。Stage 的劃分是以 ShuffleDependency 為依據(jù)的,也就是說(shuō)當(dāng)某個(gè) RDD 的運(yùn)算需要將數(shù)據(jù)進(jìn)行 Shuffle 時(shí),這個(gè)包含了 Shuffle 依賴關(guān)系的 RDD 將被用來(lái)作為輸入信息,進(jìn)而構(gòu)建一個(gè)新的 Stage。我們可以看到用這樣的方式劃分 Stage,能夠保證有依賴關(guān)系的數(shù)據(jù)可以以正確的順序執(zhí)行。根據(jù)每個(gè) Stage 所依賴的 RDD 數(shù)據(jù)的 partition 的分布,會(huì)產(chǎn)生出與 partition 數(shù)量相等的 Task,這些 Task 根據(jù) partition 的位置進(jìn)行分布。其次對(duì)于 finalStage 或是 mapStage 會(huì)產(chǎn)生不同的 Task,最后所有的 Task 會(huì)封裝到 TaskSet 內(nèi)提交到 TaskScheduler 去執(zhí)行。有興趣的讀者可以通過(guò)閱讀 DAGScheduler 和 TaskScheduler 的源碼獲取更詳細(xì)的執(zhí)行流程。
轉(zhuǎn)載:IBM