大數據面試題——Spark篇

1. 簡要講述hadoop和spark的shuffle相同和差異?

1)從高層次的的角度來看,兩者並沒有大的差別。
它都是將 mapper(Spark 裏是 ShuffleMapTask)的輸出進行 partition,不同的 partition 送到不同的 reducer(Spark 裏 reducer 可能是下一個 stage 裏的 ShuffleMapTask,也可能是 ResultTask)。Reducer 以內存作緩衝區,邊 shuffle 邊 aggregate 數據,等到數據 aggregate 好以後進行 reduce() (Spark 裏可能是後續的一系列操作)。
2)從低層次的角度來看,兩者差別不小。
Hadoop MapReduce 是 sort-based,進入 combine() 和 reduce() 的 records 必須先 sort。這樣的好處在於 combine/reduce() 可以處理大規模的數據,因爲其輸入數據可以通過外排得到(mapper 對每段數據先做排序,reducer 的 shuffle 對排好序的每段數據做歸併)。
目前的 Spark 默認選擇的是 hash-based,通常使用 HashMap 來對 shuffle 來的數據進行 aggregate,不會對數據進行提前排序。如果用戶需要經過排序的數據,那麼需要自己調用類似 sortByKey() 的操作;如果你是Spark 1.1的用戶,可以將spark.shuffle.manager設置爲sort,則會對數據進行排序。在Spark 1.2中,sort將作爲默認的Shuffle實現。
3)從實現角度來看,兩者也有不少差別。
Hadoop MapReduce 將處理流程劃分出明顯的幾個階段:map(), spill, merge, shuffle, sort, reduce() 等。每個階段各司其職,可以按照過程式的編程思想來逐一實現每個階段的功能。在 Spark 中,沒有這樣功能明確的階段,只有不同的 stage 和一系列的 transformation(),所以 spill, merge, aggregate 等操作需要蘊含在 transformation() 中。
如果我們將 map 端劃分數據、持久化數據的過程稱爲 shuffle write,而將 reducer 讀入數據、aggregate 數據的過程稱爲 shuffle read。那麼在 Spark 中,問題就變爲怎麼在 job 的邏輯或者物理執行圖中加入 shuffle write 和 shuffle read 的處理邏輯?以及兩個處理邏輯應該怎麼高效實現?
Shuffle write由於不要求數據有序,shuffle write 的任務很簡單:將數據 partition 好,並持久化。之所以要持久化,一方面是要減少內存存儲空間壓力,另一方面也是爲了 fault-tolerance。
在這裏插入圖片描述

2. Spark的工作機制?

這個知識點 南國在之前的博客中有詳細講述過,這裏簡要提一下。
用戶在client端提交作業後,會由Driver運行main方法並創建spark context上下文。
執行rdd算子,形成dag圖輸入dagscheduler,按照rdd之間的依賴關係劃分stage輸入task scheduler。 task scheduler會將stage劃分爲task set分發到各個節點的executor中執行。

3. cache和pesist的區別

1)cache和persist都是用於將一個RDD進行緩存的,這樣在之後使用的過程中就不需要重新計算了,可以大大節省程序運行時間;
2) cache只有一個默認的緩存級別MEMORY_ONLY ,cache調用了persist,而persist可以根據情況設置其它的緩存級別;
3)executor執行的時候,默認60%做cache,40%做task操作,persist最根本的函數,最底層的函數。

4. 理解Spark的shuffle過程(重要!!!)

簡單來說,Spark的shuffle過程主要是以下幾個階段:
1.Shuffle Writer:
Spark豐富了任務類型,有些任務之間數據流轉不需要通過Shuffle,但是有些任務之間還是需要通過Shuffle來傳遞數據,比如wide dependency的groupByKey。

Spark中需要Shuffle輸出的Map任務會爲每個Reduce創建對應的bucket,Map產生的結果會根據設置的partitioner得到對應的bucketId,然後填充到相應的bucket中去。每個Map的輸出結果可能包含所有的Reduce所需要的數據,所以每個Map會創建R個bucket(R是reduce的個數),M個Map總共會創建M*R個bucket。

Map創建的bucket其實對應磁盤上的一個文件,Map的結果寫到每個bucket中其實就是寫到那個磁盤文件中,這個文件也被稱爲blockFile,是Disk Block Manager管理器通過文件名的Hash值對應到本地目錄的子目錄中創建的。每個Map要在節點上創建R個磁盤文件用於結果輸出,Map的結果是直接輸出到磁盤文件上的,100KB的內存緩衝是用來創建Fast Buffered OutputStream輸出流。這種方式一個問題就是Shuffle文件過多。

針對上述Shuffle過程產生的文件過多問題,Spark有另外一種改進的Shuffle過程:consolidation Shuffle,以期顯著減少Shuffle文件的數量。在consolidation Shuffle中每個bucket並非對應一個文件,而是對應文件中的一個segment部分。Job的map在某個節點上第一次執行,爲每個reduce創建bucket對應的輸出文件,把這些文件組織成ShuffleFileGroup,當這次map執行完之後,這個ShuffleFileGroup可以釋放爲下次循環利用;當又有map在這個節點上執行時,不需要創建新的bucket文件,而是在上次的ShuffleFileGroup中取得已經創建的文件繼續追加寫一個segment;當前次map還沒執行完,ShuffleFileGroup還沒有釋放,這時如果有新的map在這個節點上執行,無法循環利用這個ShuffleFileGroup,而是隻能創建新的bucket文件組成新的ShuffleFileGroup來寫輸出。

2.Shuffle Fetcher
Reduce去拖Map的輸出數據,Spark提供了兩套不同的網絡拉取數據框架:通過socket連接去取數據;使用netty框架去取數據

每個節點的Executor會創建一個BlockManager,其中會創建一個BlockManagerWorker用於響應請求。當Reduce的GET_BLOCK的請求過來時,讀取本地文件將這個blockId的數據返回給Reduce。如果使用的是Netty框架,BlockManager會創建ShuffleSender用於發送Shuffle數據。

並不是所有的數據都是通過網絡讀取,對於在本節點的Map數據,Reduce直接去磁盤上讀取而不再通過網絡框架

Reduce拖過來數據之後以什麼方式存儲呢?Spark Map輸出的數據沒有經過排序,Spark Shuffle過來的數據也不會進行排序,Spark認爲Shuffle過程中的排序不是必須的,並不是所有類型的Reduce需要的數據都需要排序,強制地進行排序只會增加Shuffle的負擔。Reduce拖過來的數據會放在一個HashMap中,HashMap中存儲的也是<key, value>對,key是Map輸出的key,Map輸出對應這個key的所有value組成HashMap的value。Spark將Shuffle取過來的每一個<key, value>對插入或者更新到HashMap中,來一個處理一個。HashMap全部放在內存中。

Shuffle取過來的數據全部存放在內存中,對於數據量比較小或者已經在Map端做過合併處理的Shuffle數據,佔用內存空間不會太大,但是對於比如group by key這樣的操作,Reduce需要得到key對應的所有value,並將這些value組一個數組放在內存中,這樣當數據量較大時,就需要較多內存。

當內存不夠時,要不就失敗,要不就用老辦法把內存中的數據移到磁盤上放着。Spark意識到在處理數據規模遠遠大於內存空間時所帶來的不足,引入了一個具有外部排序的方案。Shuffle過來的數據先放在內存中,當內存中存儲的<key, value>對超過1000並且內存使用超過70%時,判斷節點上可用內存如果還足夠,則把內存緩衝區大小翻倍,如果可用內存不再夠了,則把內存中的<key, value>對排序然後寫到磁盤文件中。最後把內存緩衝區中的數據排序之後和那些磁盤文件組成一個最小堆,每次從最小堆中讀取最小的數據,這個和MapReduce中的merge過程類似。

這部分內容參考博客:Spark的Shuffle過程介紹

5. 數據本地性

在Spark中,數據本地性是指具體的task運行在哪臺機器上,DAG劃分stage的時候確定的。

6. Spark master使用zookeeper進行HA的,有哪些元素保存在Zookeeper ?

答:Spark通過這個參數spark.deploy.zookeeper.dir指定master元數據在zookeeper中保存的位置,包括Worker,Driver和Application以及Executors。standby節點要從zk中,獲得元數據信息,恢復集羣運行狀態,才能對外繼續提供服務,作業提交資源申請等,在恢復前是不能接受請求的。另外,Master切換需要注意2點
1)在Master切換的過程中,所有的已經在運行的程序皆正常運行!因爲Spark Application在運行前就已經通過Cluster Manager獲得了計算資源,所以在運行時Job本身的調度和處理和Master是沒有任何關係的!
2) 在Master的切換過程中唯一的影響是不能提交新的Job:一方面不能夠提交新的應用程序給集羣,因爲只有Active Master才能接受新的程序的提交請求;另外一方面,已經運行的程序中也不能夠因爲Action操作觸發新的Job的提交請求;

注意:Spark Master HA主從切換的過程不會影響集羣中已有作業的運行,因爲在程序運行之前,已經申請過資源了,driver和Executor通訊,不需要和master進行通訊的。

7. 介紹一下join操作優化經驗

join其實常見的就分爲兩類: map-side join 和 reduce-side join。
當大表和小表join時,用map-side join能顯著提高效率。將多份數據進行關聯是數據處理過程中非常普遍的用法,不過在分佈式計算系統中,這個問題往往會變的非常麻煩,因爲框架提供的 join 操作一般會將所有數據根據 key 發送到所有的 reduce 分區中去,也就是 shuffle 的過程。造成大量的網絡以及磁盤IO消耗,運行效率極其低下,這個過程一般被稱爲 reduce-side-join。如果其中有張表較小的話,我們則可以自己實現在 map 端實現數據關聯,跳過大量數據進行 shuffle 的過程,運行時間得到大量縮短,根據不同數據可能會有幾倍到數十倍的性能提升。
備註:這個題目面試中非常非常大概率見到,務必搜索相關資料掌握,這裏拋磚引玉。

8. 不啓動Spark集羣Master和worker服務,可不可以運行Spark程序?

可以,只要資源管理器第三方管理就可以,如由yarn管理,spark集羣不啓動也可以使用spark;
Spark集羣啓動的是work和master,這個其實就是資源管理框架,yarn中的resourceManager相當於master,NodeManager相當於worker,做計算是Executor,和spark集羣的work和manager可以沒關係,歸根接底還是JVM的運行,只要所在的JVM上安裝了spark就可以。

9. Spark on Yarn模式有幾種類型以及Yarn集羣的優點

Yarn集羣有兩種模式:

  • Yarn-Client模式:driver運行在本地客戶端,負責調度Application,會與Yarn集羣長生大量的網絡通信,從而導致網卡流量激增。它的好處是執行時可在本地看到所有log,便於調試。因而它一般用於測試環境。
  • Yarn-Cluster模式:driver語行在NodeManager,每次運行都是隨機分配到NodeManager機器上去,不會有網卡流量激增的問題。但他的缺點是:本地提交時看不到log,只能通過Yarn Application-log application id命令來查看。

Yarn集羣的優點:
1)與其他計算框架共享集羣資源(eg.Spark框架與MapReduce框架同時運行,如果不用Yarn進行資源分配,MapReduce分到的內存資源會很少,效率低下);資源按需分配,進而提高集羣資源利用等。
2)相較於Spark自帶的Standalone模式,Yarn的資源分配更加細緻
3)Application部署簡化,例如Spark,Storm等多種框架的應用由客戶端提交後,由Yarn負責資源的管理和調度,利用Container作爲資源隔離的單位,以它爲單位去使用內存,cpu等。
4)Yarn通過隊列的方式,管理同時運行在Yarn集羣中的多個服務,可根據不同類型的應用程序負載情況,調整對應的資源使用量,實現資源彈性管理。

10. 談談你對Yarn中container的理解

1)Container作爲資源分配和調度的基本單位,其中封裝了的資源如內存,CPU,磁盤,網絡帶寬等。 目前yarn僅僅封裝內存和CPU
2)Container由ApplicationMaster向ResourceManager申請的,由ResouceManager中的資源調度器異步分配給ApplicationMaster
3)Container的運行是由ApplicationMaster向資源所在的NodeManager發起的,Container運行時需提供內部執行的任務命令。

運行在yarn中Application有以下兩種類型:
1)運行ApplicationMaster的Container:這是由ResourceManager(向內部的資源調度器)申請和啓動的,用戶提交應用程序時,可指定唯一的ApplicationMaster所需的資源;
2)運行各類任務的Container:這是由ApplicationMaster向ResourceManager申請的,並由ApplicationMaster與NodeManager通信以啓動之。

11. Spark中的分區

Spark默認有兩種分區:hashPartitioner和rangePartitioner
(1) hashPartitioner分區:
對於指定的key,計算其hashCode,併除以分區的個數取餘,如果欲數小於0,則用餘數+分區的個數,最後返回的值就是這個key所屬的分區ID;
它的不足:原始數據不均勻時容易產生數據傾斜,極端情況下 某幾個分區的會擁有rdd的所有數據。
(2) rangePartition分區:
範圍分區的原理是儘量保證每個分區中數據量的均勻,而且分區與分區之間是有序的。但是分區內的元素是不能保證順序的。簡單而言,將一定範圍內的數據映射到某一個分區內。
(3)除上述兩個,在Spark中,我們還可以實現自定義分區。自定義分區器的時候繼承org.apache.spark.Partitioner類,實現類中的三個方法:
def numPartitions: Int:這個方法需要返回你想要創建分區的個數;
def getPartition(key: Any): Int:這個函數需要對輸入的key做計算,然後返回該key的分區ID,範圍一定是0到numPartitions-1;
equals():這個是Java標準的判斷相等的函數,之所以要求用戶實現這個函數是因爲Spark內部會比較兩個RDD的分區是否一樣。
更多詳情可看:https://www.iteblog.com/archives/1368.html

12. 談談對於Spark中的partition和HDFS中的block二者的理解

1)hdfs中的block是分佈式存儲的最小單元,等分,可設置冗餘,這樣設計有一部分磁盤空間的浪費,但是整齊的block大小,便於快速找到、讀取對應的內容;
2)Spark中的partition是彈性分佈式數據集RDD的最小單元,RDD是由分佈在各個節點上的partition組成的。partition是指的spark在計算過程中,生成的數據在計算空間內最小單元,同一份數據(RDD)的partition大小不一,數量不定,是根據application裏的算子和最初讀入的數據分塊數量決定;
3)block位於存儲空間,partition位於計算空間,block的大小是固定的、partion大小是不固定的,是從2個不同的角度去看數據。

13. Spark中task有幾種類型

Spark中的task有2種類型:
(1) shuffleMapTask類型:它是大多數task(除了Application種最後一個task之外)所屬的類型
(2) result task類型:最後一個task所屬的類型。

14. consolidate是如何優化Hash shuffle時在map端產生的小文件?

1)consolidate爲了解決Hash Shuffle同時打開過多文件導致Writer handler內存使用過大以及產生過多文件導致大量的隨機讀寫帶來的低效磁盤IO;
2)consolidate根據CPU的個數來決定每個task shuffle map端產生多少個文件,假設原來有10個task,100個reduce,每個CPU有10個CPU,那麼使用hash shuffle會產生10100=1000個文件,conslidate產生1010=100個文件;
備註:consolidate部分減少了文件和文件句柄,但在並行度很高的情況下(task很多時)還是會很多文件。

15. 簡要描述Spark寫數據的流程

1)RDD調用compute方法,進行指定分區的寫入
2)CacheManager中調用BlockManager判斷數據是否已經寫入,如果未寫,則寫入
3)BlockManager中數據與其他節點同步
4)BlockManager根據存儲級別寫入指定的存儲層
5)BlockManager向主節點彙報存儲狀態中

16. RDD的數據結構

一個RDD對象,包含下面5個核心屬性:
(1)一個分區列表,每個分區裏是RDD的部分數據(或稱數據塊)
(2)一個依賴列表,存儲依賴的其他RDD
(3)一個名爲compute的計算函數,用於計算RDD各分區的值
(4)分區器(可選),用於鍵/值類型的RDD,比如某個RDD是按照散列來分區
(5)計算各分區時優先的位置列表(可選),比如從HDFS上的文件生成RDD時,RDD分區的位置優先選擇數據所在的節點,這樣可以避免數據移動帶來的開銷。

以上內容是我平日裏學習過程中結合自己的學習筆記以及網上的資料總結而成。如有錯誤,還請看到的讀者指出,謝謝~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章