Spark core面試篇03
1.Spark使用parquet文件存儲格式能帶來哪些好處?
1) 若是說HDFS 是大數據時代分佈式文件系統首選標準,那麼parquet則是整個大數據時代文件存儲格式實時首選標準
2) 速度更快:從使用spark sql操做普通文件CSV和parquet文件速度對比上看,絕大多數狀況
會比使用csv等普通文件速度提高10倍左右,在一些普通文件系統沒法在spark上成功運行的狀況
下,使用parquet不少時候能夠成功運行
3) parquet的壓縮技術很是穩定出色,在spark sql中對壓縮技術的處理可能沒法正常的完成工做
(例如會致使lost task,lost executor)可是此時若是使用parquet就能夠正常的完成
4) 極大的減小磁盤I/o,一般狀況下可以減小75%的存儲空間,由此能夠極大的減小spark sql處理
數據的時候的數據輸入內容,尤爲是在spark1.6x中有個下推過濾器在一些狀況下能夠極大的
減小磁盤的IO和內存的佔用,(下推過濾器)
5) spark 1.6x parquet方式極大的提高了掃描的吞吐量,極大提升了數據的查找速度spark1.6和spark1.5x相比而言,提高了大約1倍的速度,在spark1.6X中,操做parquet時候cpu也進行了極大的優化,有效的下降了cpu
6) 採用parquet能夠極大的優化spark的調度和執行。咱們測試spark若是用parquet能夠有效的減小stage的執行消耗,同時能夠優化執行路徑
2.Executor之間如何共享數據?
答:基於hdfs或者基於tachyon
3.Spark累加器有哪些特色?
1)累加器在全局惟一的,只增不減,記錄全局集羣的惟一狀態
2)在exe中修改它,在driver讀取
3)executor級別共享的,廣播變量是task級別的共享
兩個application不能夠共享累加器,可是同一個app不一樣的job能夠共享
4.如何在一個不肯定的數據規模的範圍內進行排序?
爲了提升效率,要劃分劃分,劃分的範圍而且是有序的
要麼有序,要麼降序?
水塘抽樣:目的是從一個集合中選取,集合很是答,適合內存
沒法容納數據的時候使用
從N中抽取出K個,N是隨機數
5.spark hashParitioner的弊端是什麼?
答:HashPartitioner分區的原理很簡單,對於給定的key,計算其hashCode,併除於分區的個數取餘,若是餘數小於0,則用餘數+分區的個數,最後返回的值就是這個key所屬的分區ID;弊端是數據不均勻,容易致使數據傾斜,極端狀況下某幾個分區會擁有rdd的全部數據
6.RangePartitioner分區的原理?
答:RangePartitioner分區則儘可能保證每一個分區中數據量的均勻,並且分區與分區之間是有序的,也就是說一個分區中的元素確定都是比另外一個分區內的元素小或者大;可是分區內的元素是不能保證順序的。簡單的說就是將必定範圍內的數映射到某一個分區內。其原理是水塘抽樣。能夠參考這篇博文
https://www.iteblog.com/archives/1522.html
7.介紹parition和block有什麼關聯關係?
答:1)hdfs中的block是分佈式存儲的最小單元,等分,可設置冗餘,這樣設計有一部分磁盤空間的浪費,可是整齊的block大小,便於快速找到、讀取對應的內容;2)Spark中的partion是彈性分佈式數據集RDD的最小單元,RDD是由分佈在各個節點上的partion組成的。partion是指的spark在計算過程當中,生成的數據在計算空間內最小單元,同一份數據(RDD)的partion大小不一,數量不定,是根據application裏的算子和最初讀入的數據分塊數量決定;3)block位於存儲空間、partion位於計算空間,block的大小是固定的、partion大小是不固定的,是從2個不一樣的角度去看數據。
8.Spark應用程序的執行過程是什麼?
1)構建Spark Application的運行環境(啓動SparkContext),SparkContext向資源管理器(能夠是Standalone、Mesos或YARN)註冊並申請運行Executor資源;
2).資源管理器分配Executor資源並啓動StandaloneExecutorBackend,Executor運行狀況將隨着心跳發送到資源管理器上;
3).SparkContext構建成DAG圖,將DAG圖分解成Stage,並把Taskset發送給Task Scheduler。Executor向SparkContext申請Task,Task Scheduler將Task發放給Executor運行同時SparkContext將應用程序代碼發放給Executor。
4).Task在Executor上運行,運行完畢釋放全部資源。
9.hbase預分區個數和spark過程當中的reduce個數相同麼
答:和spark的map個數相同,reduce個數若是沒有設置和reduce前的map數相同。
10.如何理解Standalone模式下,Spark資源分配是粗粒度的?
答:spark默認狀況下資源分配是粗粒度的,也就是說程序在提交時就分配好資源,後面執行的時候
使用分配好的資源,除非資源出現了故障纔會從新分配。好比Spark shell啓動,已提交,一註冊,哪怕沒有任務,worker都會分配資源給executor。
11.Spark如何自定義partitioner分區器?
答:1)spark默認實現了HashPartitioner和RangePartitioner兩種分區策略,咱們也能夠本身擴展分區策略,自定義分區器的時候繼承org.apache.spark.Partitioner類,實現類中的三個方法
def numPartitions: Int:這個方法須要返回你想要建立分區的個數;
def getPartition(key: Any): Int:這個函數須要對輸入的key作計算,而後返回該key的分區ID,範圍必定是0到numPartitions-1;
equals():這個是Java標準的判斷相等的函數,之因此要求用戶實現這個函數是由於Spark內部會比較兩個RDD的分區是否同樣。
2)使用,調用parttionBy方法中傳入自定義分區對象
參考:http://blog.csdn.net/high2011/article/details/68491115
12.spark中task有幾種類型?
答:2種類型:1)result task類型,最後一個task,2是shuffleMapTask類型,除了最後一個task都是
13.union操做是產生寬依賴仍是窄依賴?
答:窄依賴
14.rangePartioner分區器特色?
答:rangePartioner儘可能保證每一個分區中數據量的均勻,並且分區與分區之間是有序的,一個分區中的元素確定都是比另外一個分區內的元素小或者大;可是分區內的元素是不能保證順序的。簡單的說就是將必定範圍內的數映射到某一個分區內。RangePartitioner做用:將必定範圍內的數映射到某一個分區內,在實現中,分界的算法尤其重要。算法對應的函數是rangeBounds
15.什麼是二次排序,你是如何用spark實現二次排序的?(互聯網公司常面)
答:就是考慮2個維度的排序,key相同的狀況下如何排序,參考博文:http://blog.csdn.net/sundujing/article/details/51399606
16.如何使用Spark解決TopN問題?(互聯網公司常面)
答:常見的面試題,參考博文:http://www.cnblogs.com/yurunmiao/p/4898672.html
17.如何使用Spark解決分組排序問題?(互聯網公司常面)
組織數據形式:
aa 11
bb 11
cc 34
aa 22
bb 67
cc 29
aa 36
bb 33
cc 30
aa 42
bb 44
cc 49
需求:
一、對上述數據按key值進行分組
二、對分組後的值進行排序
三、截取分組後值得top 3位以key-value形式返回結果
答案:以下
----------------------
val groupTopNRdd = sc.textFile("hdfs://db02:8020/user/hadoop/groupsorttop/groupsorttop.data")
groupTopNRdd.map(_.split(" ")).map(x => (x(0),x(1))).groupByKey().map(
x => {
val xx = x._1
val yy = x._2
(xx,yy.toList.sorted.reverse.take(3))
}
).collect
---------------------
18.窄依賴父RDD的partition和子RDD的parition是否是都是一對一的關係?
答:不必定,除了一對一的窄依賴,還包含一對固定個數的窄依賴(就是對父RDD的依賴的Partition的數量不會隨着RDD數量規模的改變而改變),好比join操做的每一個partiion僅僅和已知的partition進行join,這個join操做是窄依賴,依賴固定數量的父rdd,由於是肯定的partition關係
19.Hadoop中,Mapreduce操做的mapper和reducer階段至關於spark中的哪幾個算子?
答:至關於spark中的map算子和reduceByKey算子,固然仍是有點區別的,MR會自動進行排序的,spark要看你用的是什麼partitioner
20.什麼是shuffle,以及爲何須要shuffle?
shuffle中文翻譯爲洗牌,須要shuffle的緣由是:某種具備共同特徵的數據匯聚到一個計算節點上進行計算
21.不須要排序的hash shuffle是否必定比須要排序的sort shuffle速度快?
答:不必定!!當數據規模小,Hash shuffle快於Sorted Shuffle數據規模大的時候;當數據量大,sorted Shuffle會比Hash shuffle快不少,由於數量大的有不少小文件,不均勻,甚至出現數據傾斜,消耗內存大,1.x以前spark使用hash,適合處理中小規模,1.x以後,增長了Sorted shuffle,Spark更能勝任大規模處理了。
22.Spark中的HashShufle的有哪些不足?
答:1)shuffle產生海量的小文件在磁盤上,此時會產生大量耗時的、低效的IO操做;2).容易致使內存不夠用,因爲內存須要保存海量的文件操做句柄和臨時緩存信息,若是數據處理規模比較大的化,容易出現OOM;3)容易出現數據傾斜,致使OOM
23.conslidate是如何優化Hash shuffle時在map端產生的小文件?
答:1)conslidate爲了解決Hash Shuffle同時打開過多文件致使Writer handler內存使用過大以及產生過多文件致使大量的隨機讀寫帶來的低效磁盤IO;2)conslidate根據CPU的個數來決定每一個task shuffle map端產生多少個文件,假設原來有10個task,100個reduce,每一個CPU有10個CPU
那麼使用hash shuffle會產生10100=1000個文件,conslidate產生1010=100個文件
備註:conslidate部分減小了文件和文件句柄,並行讀很高的狀況下(task不少時)仍是會不少文件
24.Sort-basesd shuffle產生多少個臨時文件
答:2Map階段全部的task數量,Mapper階段中並行的Partition的總數量,其實就是Mapper端task
25.Sort-based shuffle的缺陷?
1) 若是mapper中task的數量過大,依舊會產生不少小文件,此時在shuffle傳遞數據的過程當中reducer段,reduce會須要同時大量的記錄進行反序列化,致使大量的內存消耗和GC的巨大負擔,形成系統緩慢甚至崩潰
2)若是須要在分片內也進行排序,此時須要進行mapper段和reducer段的兩次排序
26.Spark shell啓動時會啓動derby?
答: spark shell啓動會啓動spark sql,spark sql默認使用derby保存元數據,可是儘可能不要用derby,它是單實例,不利於開發。會在本地生成一個文件metastore_db,若是啓動報錯,就把那個文件給刪了 ,derby數據庫是單實例,不能支持多個用戶同時操做,儘可能避免使用
27.spark.default.parallelism這個參數有什麼意義,實際生產中如何設置?
答:1)參數用於設置每一個stage的默認task數量。這個參數極爲重要,若是不設置可能會直接影響你的Spark做業性能;2)不少人都不會設置這個參數,會使得集羣很是低效,你的cpu,內存再多,若是task始終爲1,那也是浪費,spark官網建議task個數爲CPU的核數executor的個數的2~3倍。
28.spark.storage.memoryFraction參數的含義,實際生產中如何調優?
答:1)用於設置RDD持久化數據在Executor內存中能佔的比例,默認是0.6,,默認Executor 60%的內存,能夠用來保存持久化的RDD數據。根據你選擇的不一樣的持久化策略,若是內存不夠時,可能數據就不會持久化,或者數據會寫入磁盤。2)若是持久化操做比較多,能夠提升spark.storage.memoryFraction參數,使得更多的持久化數據保存在內存中,提升數據的讀取性能,若是shuffle的操做比較多,有不少的數據讀寫操做到JVM中,那麼應該調小一點,節約出更多的內存給JVM,避免過多的JVM gc發生。在web ui中觀察若是發現gc時間很長,能夠設置spark.storage.memoryFraction更小一點。
29.spark.shuffle.memoryFraction參數的含義,以及優化經驗?
答:1)spark.shuffle.memoryFraction是shuffle調優中 重要參數,shuffle從上一個task拉去數據過來,要在Executor進行聚合操做,聚合操做時使用Executor內存的比例由該參數決定,默認是20%
若是聚合時數據超過了該大小,那麼就會spill到磁盤,極大下降性能;2)若是Spark做業中的RDD持久化操做較少,shuffle操做較多時,建議下降持久化操做的內存佔比,提升shuffle操做的內存佔比比例,避免shuffle過程當中數據過多時內存不夠用,必須溢寫到磁盤上,下降了性能。此外,若是發現做業因爲頻繁的gc致使運行緩慢,意味着task執行用戶代碼的內存不夠用,那麼一樣建議調低這個參數的值
30.介紹一下你對Unified Memory Management內存管理模型的理解?
答:Spark中的內存使用分爲兩部分:執行(execution)與存儲(storage)。執行內存主要用於shuffles、joins、sorts和aggregations,存儲內存則用於緩存或者跨節點的內部數據傳輸。1.6以前,對於一個Executor,內存都有哪些部分構成:
1)ExecutionMemory。這片內存區域是爲了解決 shuffles,joins, sorts and aggregations 過程當中爲了不頻繁IO須要的buffer。 經過spark.shuffle.memoryFraction(默認 0.2) 配置。
2)StorageMemory。這片內存區域是爲了解決 block cache(就是你顯示調用dd.cache, rdd.persist等方法), 還有就是broadcasts,以及task results的存儲。能夠經過參數 spark.storage.memoryFraction(默認0.6)。設置
3)OtherMemory。給系統預留的,由於程序自己運行也是須要內存的。 (默認爲0.2).
傳統內存管理的不足:
1).Shuffle佔用內存0.2*0.8,內存分配這麼少,可能會將數據spill到磁盤,頻繁的磁盤IO是很大的負擔,Storage內存佔用0.6,主要是爲了迭代處理。傳統的Spark內存分配對操做人的要求很是高。(Shuffle分配內存:ShuffleMemoryManager, TaskMemoryManager,ExecutorMemoryManager)一個Task得到所有的Execution的Memory,其餘Task過來就沒有內存了,只能等待。
2).默認狀況下,Task在線程中可能會佔滿整個內存,分片數據特別大的狀況下就會出現這種狀況,其餘Task沒有內存了,剩下的cores就空閒了,這是巨大的浪費。這也是人爲操做的不當形成的。
3).MEMORY_AND_DISK_SER的storage方式,得到RDD的數據是一條條獲取,iterator的方式。若是內存不夠(spark.storage.unrollFraction),unroll的讀取數據過程,就是看內存是否足夠,若是足夠,就下一條。unroll的space是從Storage的內存空間中得到的。unroll的方式失敗,就會直接放磁盤。
4). 默認狀況下,Task在spill到磁盤以前,會將部分數據存放到內存上,若是獲取不到內存,就不會執行。永無止境的等待,消耗CPU和內存。
在此基礎上,Spark提出了UnifiedMemoryManager,再也不分ExecutionMemory和Storage Memory,實際上仍是分的,只不過是Execution Memory訪問Storage Memory,Storage Memory也能夠訪問Execution Memory,若是內存不夠,就會去借。html