Spark-SQL 面試準備 1

Spark Knowledge NO.1

1. spark中的RDD是什麼,有哪些特性?

答:RDD(Resilient Distributed Dataset)叫做分佈式數據集,是spark中最基本的數據抽象,它代表一個不可變可分區,裏面的元素可以並行計算的集合

Resilient:表示彈性的,彈性表示

Dataset:就是一個集合,用於存放數據的

Destributed:分佈式,可以並行在集羣計算

1.RDD中的數據可以存儲在內存或者磁盤中;

2.RDD中的分區是可以改變的;

五大特性:

  1. A list of partitions:一個分區列表,RDD中的數據都存儲在一個分區列表中
  2. A function for computing each split:作用在每一個分區中的函數
  3. A list of dependencies on other RDDs:一個RDD依賴於其他多個RDD,這個點很重要,RDD的容錯機制就是依據這個特性而來的
  4. Optionally, a Partitioner for key-value RDDs(eg:to say that the RDD is hash-partitioned):可選的,針對於kv類型的RDD纔有這個特性,作用是決定了數據的來源以及數據處理後的去向
  5. 可選項,數據本地性,數據位置最優

2. 概述一下spark中的常用算子區別(map, mapPartitions, foreach, foreachPatition)

答:map:用於遍歷RDD,將函數應用於每一個元素,返回新的RDD(transformation算子)

foreach:用於遍歷RDD,將函數應用於每一個元素,無返回值(action算子)

mapPatitions:用於遍歷操作RDD中的每一個分區,返回生成一個新的RDD(transformation算子)

foreachPatition:用於遍歷操作RDD中的每一個分區,無返回值(action算子)

總結:一般使用mapPatitions和foreachPatition算子比map和foreach更加高效,推薦使用

3. 談談spark中的寬窄依賴:

img

​ 圖中左邊是寬依賴,父RDD的4號分區數據劃分到子RDD的多個分區(一分區對多分區),這就表明有shuffle過程,父分區數據經過shuffle過程的hash分區器(也可自定義分區器)劃分到子RDD。例如GroupByKey,reduceByKey,join,sortByKey等操作。

​ 圖右邊是窄依賴,父RDD的每個分區的數據直接到子RDD的對應一個分區(一分區對一分區),例如1號到5號分區的數據都只進入到子RDD的一個分區,這個過程沒有shuffle。Spark中Stage的劃分就是通過shuffle來劃分。(shuffle可理解爲數據的從原分區打亂重組到新的分區)如:map,filter

Spark基於lineage的容錯性是指,如果一個RDD出錯,那麼可以從它的所有父RDD重新計算所得,如果一個RDD僅有一個父RDD(即窄依賴),那麼這種重新計算的代價會非常小。

Spark基於Checkpoint(物化)的容錯機制何解?在上圖中,寬依賴得到的結果(經歷過Shuffle過程)是很昂貴的,因此,Spark將此結果物化到磁盤上了,以備後面使用

對於join操作有兩種情況,如果join操作的每個partition 僅僅和已知的Partition進行join,此時的join操作就是窄依賴;其他情況的join操作就是寬依賴;因爲是確定的Partition數量的依賴關係,所以就是窄依賴,得出一個推論,窄依賴不僅包含一對一的窄依賴,還包含一對固定個數的窄依賴(也就是說對父RDD的依賴的Partition的數量不會隨着RDD數據規模的改變而改變)

4. spark中如何劃分stage:

答:概念:Spark任務會根據RDD之間的依賴關係,形成一個DAG有向無環圖,DAG會提交給DAGScheduler,DAGScheduler會把DAG劃分相互依賴的多個stage,劃分依據就是寬窄依賴,遇到寬依賴就劃分stage,每個stage包含一個或多個task,然後將這些task以taskSet的形式提交給TaskScheduler運行,stage是由一組並行的task組成。

  1. 一個 job,就是由一個 rdd 的 action 觸發的動作,可以簡單的理解爲,當你需要執行一個 rdd 的 action 的時候,會生成一個 job。

  2. stage : stage 是一個 job 的組成單位,就是說,一個 job 會被切分成 1 個或 1 個以上的 stage,然後各個 stage 會按照執行順序依次執行。

  3. task :即 stage 下的一個任務執行單元,一般來說,一個 rdd 有多少個partition,就會有多少個 task,因爲每一個 task 只是處理一個partition 上的數據。

  4. stage 的劃分標準就是寬依賴:何時產生寬依賴就會產生一個新的stage,例如reduceByKey,groupByKey,join的算子,會導致寬依賴的產生;

  5. 切割規則:從後往前,遇到寬依賴就切割stage;

  6. 每個Stage裏面的Task的數量是由該Stage中最後 一個RDD的Partition數量決定的;

  7. 最後一個Stage裏面的任務的類型是ResultTask,前面所有其他Stage裏面的任務類型都是ShuffleMapTask;

  8. 代表當前Stage的算子一定是該Stage的最後一個計算步驟;

    圖解:

    img

5.計算格式:pipeline管道計算模式,piepeline只是一種計算思想,一種模式。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-1Q9MMWiR-1579501612033)(C:\Users\sqian\Documents\Others\images\spark003.png)]

通過上圖我們可以看到,RDD_C、RDD_D、RDD_E、RDD_F都是窄依賴關係,所以這個將他們劃分爲Stage2,Stage1和Stage3同理。而每一個Stage其實就是一併並行的任務,就像上圖,RDD_C、RDD_D、RDD_F之間有兩個並行的task0和task1;RDD_E和RDD_F之間有兩個並行的task2,task3,pipeline並行計算就是基於這些task的。

由此可以看出,在spark中pipeline是一個partition對應一個partition,所以在stage內部只有窄依賴,stage與stage之間是寬依賴。(pipeline詳解

spark的pipeline管道計算模式相當於執行了一個高階函數,也就是說來一條數據然後計算一條數據,會把所有的邏輯走完,然後落地,而MapReduce是1+1=2,2+1=3這樣的計算模式,也就是計算完落地,然後再計算,然後再落地到磁盤或者內存,最後數據是落在計算節點上,按reduce的hash分區落地。管道計算模式完全基於內存計算,所以比MapReduce快的原因。

管道中的RDD會在shuffle write的時候,對RDD進行持久化的時候。

優化

stage的task的並行度是由stage的最後一個RDD的分區數來決定的,一般來說,一個partition對應一個task,但最後reduce的時候可以手動改變reduce的個數,也就是改變最後一個RDD的分區數,也就改變了並行度。例如:reduceByKey(+,3)

總結:提高stage的並行度:reduceByKey(+,patition的個數) ,join(+,patition的個數)

6. DAGScheduler 分析:

答:概述:是一個面向stage 的調度器;

主要入參有:dagScheduler.runJob(rdd, cleanedFunc, partitions, callSite, allowLocal,resultHandler, localProperties.get)

​ rdd: final RDD;

​ cleanedFunc: 計算每個分區的函數;

​ resultHander: 結果偵聽器;

主要功能:

​ 1. 接受用戶提交的job;

​ 2. 將job根據類型劃分爲不同的stage,記錄那些RDD,stage被物化,並在每一個stage內產生一系列的task,並封裝成taskset;

​ 3. 決定每個task的最佳位置,任務在數據所在節點上運行,並結合當前的緩存情況,將taskSet提交給TaskScheduler;

​ 4. 重新提交shuffle輸出丟失的stage給taskScheduler;

注:一個stage內部的錯誤不是由shuffle輸出丟失造成的,DAGScheduler是不管的,由TaskScheduler負責嘗試重新提交task執行。

7.Job的生成:

答:一旦driver程序中出現action,就會生成一個job,比如:count等,向DAGScheduler提交job,如果driver程序後面還有action,那麼其他action也會對應生成相應的job,所以,driver端有多少action就會提交多少job,這可能就是爲什麼spark將driver程序稱爲application而不是job 的原因。每一個job可能會包含一個或者多個stage,最後一個stage生成result,在提交job 的過程中,DAGScheduler會首先從後往前劃分stage,劃分的標準就是寬依賴,一旦遇到寬依賴就劃分,然後先提交沒有父階段的stage們,並在提交過程中,計算該stage的task數目以及類型,並提交具體的task,在這些無父階段的stage提交完之後,依賴該stage 的stage纔會提交。

8.有向無環圖:

答:DAG,有向無環圖,簡單的來說,就是一個由頂點和有方向性的邊構成的圖中,從任意一個頂點出發,沒有任意一條路徑會將其帶回到出發點的頂點位置,爲每個spark job計算具有依賴關係的多個stage任務階段,通常根據shuffle來劃分stage,如reduceByKey,groupByKey等涉及到shuffle的transformation就會產生新的stage ,然後將每個stage劃分爲具體的一組任務,以TaskSets的形式提交給底層的任務調度模塊來執行,其中不同stage之前的RDD爲寬依賴關係,TaskScheduler任務調度模塊負責具體啓動任務,監控和彙報任務運行情況。

9.Wordcount示例

img

Spark的運行架構由Driver(可理解爲master)和Executor(可理解爲worker或slave)組成,Driver負責把用戶代碼進行DAG切分,劃分爲不同的Stage,然後把每個Stage對應的task調度提交到Executor進行計算,這樣Executor就並行執行同一個Stage的task。

10.RDD是什麼以及它的分類:

算子的定義:RDD中定義的函數,可以對RDD中的數據進行轉換和操作。下面根據算子類型的分類進行總結:

1. value型算子
從輸入到輸出可分爲一對一(包括cache)、多對一、多對多、輸出分區爲輸入分區自激
1)一對一,
map,簡單的一對一映射,集合不變;
flatMap,一對一映射,並將最後映射結果整合;
mappartitions,對分區內元素進行迭代操作,例如過濾等,然後分區不變
glom,將分區內容轉換成數據
2)多對一,
union,相同數據類型RDD進行合併,並不去重
cartesian,對RDD內的所有元素進行笛卡爾積操作
3)多對多,
groupBy,將元素通過函數生成相應的Key,然後轉化爲Key-value格式
4)輸出分區爲出入分區子集,
filter,對RDD進行過濾操作,結果分區不調整
distinct,對RDD進行去重操作,
subtract,RDD間進行減操作,去除相同數據元素
sample/takeSample 對RDD進行採樣操作
5)cache,
cache,將RDD數據原樣存入內存
persist,對RDD數據進行緩存操作

2. Key-Value算子
Key-Value算子大致可分爲一對一,聚集,連接三類操作
1)一對一,
mapValues,針對數值對中的Value進行上面提到的map操作
2)聚集操作
combineByKey、reduceByKey、partitionBy、cogroup
3)連接
join、leftOutJoin、rightOutJoin
3. Actions算子
該算子通過SparkContext執行提交作業操作,出發RDD DAG的執行
1)foreach, 對RDD中每個元素進行操作,但是不返回RDD或者Array,只返回Unit
2)存入HDFS,saveAsTextFile,saveAsObjectFile
3)scala數據格式,collect,collectAsMap,reduceByKeyLocally, lookup, count, top, reduce, fold, aggregate

發佈了79 篇原創文章 · 獲贊 45 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章