如果其中有一張表爲小表,直接使用map端join的方式(map端加載小表)進行聚合。
如果兩張都是大表,那麼採用聯合key,聯合key的第一個組成部分是join on中的公共字段,第二部分是一個flag,0代表表A,1代表表B,由此讓Reduce區分客戶信息和訂單信息;在Mapper中同時處理兩張表的信息,將join on公共字段相同的數據劃分到同一個分區中,進而傳遞到一個Reduce中,然後在Reduce中實現聚合。
2、請談一下Hive的特點,Hive和RDBMS有什麼異同?
hive是基於Hadoop的一個數據倉庫工具,可以將結構化的數據文件映射爲一張數據庫表,並提供完整的sql查詢功能,可以將sql語句轉換爲MapReduce任務進行運行。其優點是學習成本低,可以通過類SQL語句快速實現簡單的MapReduce統計,不必開發專門的MapReduce應用,十分適合數據倉庫的統計分析,但是Hive不支持實時查詢。
Hive與關係型數據庫的區別:
Order by:會對輸入做全局排序,因此只有一個reducer(多個reducer無法保證全局有序)。只有一個reducer,會導致當輸入規模較大時,需要較長的計算時間。
Sort by:不是全局排序,其在數據進入reducer前完成排序。1
Distribute by:按照指定的字段對數據進行劃分輸出到不同的reduce中。
Cluster by:除了具有 distribute by 的功能外還兼具 sort by 的功能。
4、寫出Hive中split、coalesce及collect_list函數的用法(可舉例)?
split將字符串轉化爲數組,即:split('a,b,c,d' , ',') ==> ["a","b","c","d"]。
coalesce(T v1, T v2, …) 返回參數中的第一個非空值;如果所有值都爲 NULL,那麼返回NULL。
collect_list列出該字段所有的值,不去重 => select collect_list(id) from table。
5、 Hive有哪些方式保存元數據,各有哪些特點?
Hive支持三種不同的元存儲服務器,分別爲:內嵌式元存儲服務器、本地元存儲服務器、遠程元存儲服務器,每種存儲方式使用不同的配置參數。
內嵌式元存儲主要用於單元測試,在該模式下每次只有一個進程可以連接到元存儲,Derby是內嵌式元存儲的默認數據庫。
在本地模式下,每個Hive客戶端都會打開到數據存儲的連接並在該連接上請求SQL查詢。
在遠程模式下,所有的Hive客戶端都將打開一個到元數據服務器的連接,該服務器依次查詢元數據,元數據服務器和客戶端之間使用Thrift協議通信。
6、Hive內部表和外部表的區別?
創建表時:創建內部表時,會將數據移動到數據倉庫指向的路徑;若創建外部表,僅記錄數據所在的路徑,不對數據的位置做任何改變。
刪除表時:在刪除表的時候,內部表的元數據和數據會被一起刪除, 而外部表只刪除元數據,不刪除數據。這樣外部表相對來說更加安全些,數據組織也更加靈活,方便共享源數據。
7、Hive的函數:UDF、UDAF、UDTF的區別?
UDF:單行進入,單行輸出
UDAF:多行進入,單行輸出
UDTF:單行輸入,多行輸出
8、所有的Hive任務都會有MapReduce的執行嗎?
不是,從Hive0.10.0版本開始,對於簡單的不需要聚合的類似SELECT from
LIMIT n語句,不需要起MapReduce job,直接通過Fetch task獲取數據。
9、說說對Hive桶表的理解?
桶表是對數據某個字段
進行哈希取值,然後放到不同文件中存儲。
數據加載到桶表時,會對字段取hash值,然後與桶的數量取模。把數據放到對應的文件中。物理上,每個桶就是表(或分區)目錄裏的一個文件,一個作業產生的桶(輸出文件)和reduce任務個數相同。
桶表專門用於抽樣查詢,是很專業性的,不是日常用來存儲數據的表,需要抽樣查詢時,才創建和使用桶表。
10、Hive底層與數據庫交互原理?
Hive 的查詢功能是由 HDFS 和 MapReduce結合起來實現的,對於大規模數據查詢還是不建議在 hive 中,因爲過大數據量會造成查詢十分緩慢。Hive 與 MySQL的關係:只是借用 MySQL來存儲 hive 中的表的元數據信息,稱爲 metastore(元數據信息)。
11、Hive本地模式
大多數的Hadoop Job是需要Hadoop提供的完整的可擴展性來處理大數據集的。不過,有時Hive的輸入數據量是非常小的。在這種情況下,爲查詢觸發執行任務時消耗可能會比實際job的執行時間要多的多。對於大多數這種情況,Hive可以通過本地模式在單臺機器上處理所有的任務。對於小數據集,執行時間可以明顯被縮短。
用戶可以通過設置hive.exec.mode.local.auto的值爲true,來讓Hive在適當的時候自動啓動這個優化。
12、Hive 中的壓縮格式TextFile、SequenceFile、RCfile 、ORCfile各有什麼區別?
1、TextFile
默認格式,存儲方式爲行存儲,數據不做壓縮,磁盤開銷大,數據解析開銷大。可結合Gzip、Bzip2使用(系統自動檢查,執行查詢時自動解壓),但使用這種方式,壓縮後的文件不支持split,Hive不會對數據進行切分,從而無法對數據進行並行操作。並且在反序列化過程中,必須逐個字符判斷是不是分隔符和行結束符,因此反序列化開銷會比SequenceFile高几十倍。
2、SequenceFile
SequenceFile是Hadoop API提供的一種二進制文件支持,存儲方式爲行存儲,其具有使用方便、可分割、可壓縮的特點。
SequenceFile支持三種壓縮選擇:NONE
,RECORD
,BLOCK
。Record壓縮率低,一般建議使用BLOCK壓縮。
優勢是文件和hadoop api中的MapFile是相互兼容的
3、RCFile
存儲方式:數據按行分塊,每塊按列存儲。結合了行存儲和列存儲的優點:
首先,RCFile 保證同一行的數據位於同一節點,因此元組重構的開銷很低;
其次,像列存儲一樣,RCFile 能夠利用列維度的數據壓縮,並且能跳過不必要的列讀取;
4、ORCFile
存儲方式:數據按行分塊 每塊按照列存儲。
壓縮快、快速列存取。
效率比rcfile高,是rcfile的改良版本。
小結:
相比TEXTFILE和SEQUENCEFILE,RCFILE由於列式存儲方式,數據加載時性能消耗較大,但是具有較好的壓縮比和查詢響應。
數據倉庫的特點是一次寫入、多次讀取,因此,整體來看,RCFILE相比其餘兩種格式具有較明顯的優勢。
13、Hive表關聯查詢,如何解決數據傾斜的問題?
1)傾斜原因:map輸出數據按key Hash的分配到reduce中,由於key分佈不均勻、業務數據本身的特、建表時考慮不周、等原因造成的reduce 上的數據量差異過大。
(1)key分佈不均勻;
(2)業務數據本身的特性;
(3)建表時考慮不周;
(4)某些SQL語句本身就有數據傾斜;
如何避免:對於key爲空產生的數據傾斜,可以對其賦予一個隨機值。
2)解決方案
(1)參數調節:
hive.map.aggr = true
hive.groupby.skewindata=true
有數據傾斜的時候進行負載均衡,當選項設定位true,生成的查詢計劃會有兩個MR Job。第一個MR Job中,Map的輸出結果集合會隨機分佈到Reduce中,每個Reduce做部分聚合操作,並輸出結果,這樣處理的結果是相同的Group By Key有可能被分發到不同的Reduce中,從而達到負載均衡的目的;第二個MR Job再根據預處理的數據結果按照Group By Key 分佈到 Reduce 中(這個過程可以保證相同的 Group By Key 被分佈到同一個Reduce中),最後完成最終的聚合操作。
(2)SQL 語句調節:
① 選用join key分佈最均勻的表作爲驅動表。做好列裁剪和filter操作,以達到兩表做join 的時候,數據量相對變小的效果。
② 大小表Join:
使用map join讓小的維度表(1000 條以下的記錄條數)先進內存。在map端完成reduce。
③ 大表Join大表:
把空值的key變成一個字符串加上隨機數,把傾斜的數據分到不同的reduce上,由於null 值關聯不上,處理後並不影響最終結果。
④ count distinct大量相同特殊值:
count distinct 時,將值爲空的情況單獨處理,如果是計算count distinct,可以不用處理,直接過濾,在最後結果中加1。如果還有其他計算,需要進行group by,可以先將值爲空的記錄單獨處理,再和其他計算結果進行union。
14、Fetch抓取
Fetch抓取是指,Hive中對某些情況的查詢可以不必使用MapReduce計算。例如:SELECT * FROM employees;在這種情況下,Hive可以簡單地讀取employee對應的存儲目錄下的文件,然後輸出查詢結果到控制檯。
在hive-default.xml.template文件中hive.fetch.task.conversion默認是more,老版本hive默認是minimal,該屬性修改爲more以後,在全局查找、字段查找、limit查找等都不走mapreduce。
15、小表、大表Join
將key相對分散,並且數據量小的表放在join的左邊,這樣可以有效減少內存溢出錯誤發生的機率;再進一步,可以使用Group讓小的維度表(1000條以下的記錄條數)先進內存。在map端完成reduce。
實際測試發現:新版的hive已經對小表JOIN大表和大表JOIN小表進行了優化。小表放在左邊和右邊已經沒有明顯區別。
16、大表Join大表
1)空KEY過濾 有時join超時是因爲某些key對應的數據太多,而相同key對應的數據都會發送到相同的reducer上,從而導致內存不夠。此時我們應該仔細分析這些異常的key,很多情況下,這些key對應的數據是異常數據,我們需要在SQL語句中進行過濾。例如key對應的字段爲空。2)空key轉換 有時雖然某個key爲空對應的數據很多,但是相應的數據不是異常數據,必須要包含在join的結果中,此時我們可以表a中key爲空的字段賦一個隨機的值,使得數據隨機均勻地分不到不同的reducer上。
17、Group By
默認情況下,Map階段同一Key數據分發給一個reduce,當一個key數據過大時就傾斜了。 並不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端進行部分聚合,最後在Reduce端得出最終結果。1)開啓Map端聚合參數設置 (1)是否在Map端進行聚合,默認爲True hive.map.aggr = true (2)在Map端進行聚合操作的條目數目 hive.groupby.mapaggr.checkinterval = 100000 (3)有數據傾斜的時候進行負載均衡(默認是false) hive.groupby.skewindata = true 當選項設定爲 true,生成的查詢計劃會有兩個MR Job。第一個MR Job中,Map的輸出結果會隨機分佈到Reduce中,每個Reduce做部分聚合操作,並輸出結果,這樣處理的結果是相同的Group By Key有可能被分發到不同的Reduce中,從而達到負載均衡的目的;第二個MR Job再根據預處理的數據結果按照Group By Key分佈到Reduce中(這個過程可以保證相同的Group By Key被分佈到同一個Reduce中),最後完成最終的聚合操作。
18、Count(Distinct) 去重統計
數據量小的時候無所謂,數據量大的情況下,由於COUNT DISTINCT操作需要用一個Reduce Task來完成,這一個Reduce需要處理的數據量太大,就會導致整個Job很難完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替換
19、笛卡爾積
儘量避免笛卡爾積,join的時候不加on條件,或者無效的on條件,Hive只能使用1個reducer來完成笛卡爾積
20、行列過濾
列處理:在SELECT中,只拿需要的列,如果有,儘量使用分區過濾,少用SELECT *。
行處理:在分區剪裁中,當使用外關聯時,如果將副表的過濾條件寫在Where後面,那麼就會先全表關聯,之後再過濾。
21、並行執行
Hive會將一個查詢轉化成一個或者多個階段。這樣的階段可以是MapReduce階段、抽樣階段、合併階段、limit階段。或者Hive執行過程中可能需要的其他階段。默認情況下,Hive一次只會執行一個階段。不過,某個特定的job可能包含衆多的階段,而這些階段可能並非完全互相依賴的,也就是說有些階段是可以並行執行的,這樣可能使得整個job的執行時間縮短。不過,如果有更多的階段可以並行執行,那麼job可能就越快完成。
通過設置參數hive.exec.parallel值爲true,就可以開啓併發執行。不過,在共享集羣中,需要注意下,如果job中並行階段增多,那麼集羣利用率就會增加。
Hadoop部分:
1、集羣的最主要瓶頸
磁盤IO,網絡帶寬
2、Hadoop運行模式
單機版、僞分佈式模式、完全分佈式模式
3、Hadoop生態圈的組件並做簡要描述
1)Zookeeper:是一個開源的分佈式應用程序協調服務,基於zookeeper可以實現同步服務,配置維護,命名服務。
2)Flume:一個高可用的,高可靠的,分佈式的海量日誌採集、聚合和傳輸的系統。
3)Hbase:是一個分佈式的、面向列的開源數據庫, 利用Hadoop HDFS作爲其存儲系統。
4)Hive:基於Hadoop的一個數據倉庫工具,可以將結構化的數據檔映射爲一張數據庫表,並提供簡單的sql 查詢功能,可以將sql語句轉換爲MapReduce任務進行運行。
5)Sqoop:將一個關係型數據庫中的數據導進到Hadoop的 HDFS中,也可以將HDFS的數據導進到關係型數據庫中。
4、解釋“hadoop”和“hadoop 生態系統”兩個概念
Hadoop是指Hadoop框架本身;hadoop生態系統,不僅包含hadoop,還包括保證hadoop框架正常高效運行其他框架,比如zookeeper、Flume、Hbase、Hive、Sqoop等輔助框架。
5、請列出正常工作的Hadoop集羣中Hadoop都分別需要啓動哪些進程,它們的作用分別是什麼?
1)NameNode:它是hadoop中的主服務器,管理文件系統名稱空間和對集羣中存儲的文件的訪問,保存有metadate。
2)SecondaryNameNode:它不是namenode的冗餘守護進程,而是提供週期檢查點和清理任務。幫助NN合併editslog,減少NN啓動時間。
3)DataNode:它負責管理連接到節點的存儲(一個集羣中可以有多個節點)。每個存儲數據的節點運行一個datanode守護進程。
4)ResourceManager(JobTracker):JobTracker負責調度DataNode上的工作。每個DataNode有一個TaskTracker,它們執行實際工作。
5)NodeManager:(TaskTracker)執行任務。
6)DFSZKFailoverController:高可用時它負責監控NN的狀態,並及時的把狀態信息寫入ZK。它通過一個獨立線程週期性的調用NN上的一個特定接口來獲取NN的健康狀態。FC也有選擇誰作爲Active NN的權利,因爲最多隻有兩個節點,目前選擇策略還比較簡單(先到先得,輪換)。
7)JournalNode:高可用情況下存放namenode的editlog文件。
6、談談Hadoop序列化和反序列化及自定義bean對象實現序列化?
1)序列化和反序列化
(1)序列化就是把內存中的對象,轉換成字節序列(或其他數據傳輸協議)以便於存儲(持久化)和網絡傳輸。
(2)反序列化就是將收到字節序列(或其他數據傳輸協議)或者是硬盤的持久化數據,轉換成內存中的對象。
(3)Java的序列化是一個重量級序列化框架(Serializable),一個對象被序列化後,會附帶很多額外的信息(各種校驗信息,header,繼承體系等),不便於在網絡中高效傳輸。所以,hadoop自己開發了一套序列化機制(Writable),精簡、高效。
2)自定義bean對象要想序列化傳輸步驟及注意事項:
(1)必須實現Writable接口
(2)反序列化時,需要反射調用空參構造函數,所以必須有空參構造
(3)重寫序列化方法
(4)重寫反序列化方法
(5)注意反序列化的順序和序列化的順序完全一致
(6)要想把結果顯示在文件中,需要重寫toString(),且用"\t"分開,方便後續用
(7)如果需要將自定義的bean放在key中傳輸,則還需要實現comparable接口,因爲mapreduce框中的shuffle過程一定會對key進行排序
7、FileInputFormat切片機制
job提交流程源碼詳解
waitForCompletion()
submit();
// 1、建立連接
connect();
// 1)創建提交job的代理
new Cluster(getConfiguration());
// (1)判斷是本地yarn還是遠程
initialize(jobTrackAddr, conf);
// 2、提交job
submitter.submitJobInternal(Job.this, cluster)
// 1)創建給集羣提交數據的Stag路徑
Path jobStagingArea = JobSubmissionFiles.getStagingDir(cluster, conf);
// 2)獲取jobid ,並創建job路徑
JobID jobId = submitClient.getNewJobID();
// 3)拷貝jar包到集羣
copyAndConfigureFiles(job, submitJobDir);
rUploader.uploadFiles(job, jobSubmitDir);
// 4)計算切片,生成切片規劃文件
writeSplits(job, submitJobDir);
maps = writeNewSplits(job, jobSubmitDir);
input.getSplits(job);
// 5)向Stag路徑寫xml配置文件
writeConf(conf, submitJobFile);
conf.writeXml(out);
// 6)提交job,返回提交狀態
status = submitClient.submitJob(jobId, submitJobDir.toString(), job.getCredentials());
8、在一個運行的Hadoop 任務中,什麼是InputSplit?
FileInputFormat源碼解析(input.getSplits(job))
(1)找到你數據存儲的目錄。
(2)開始遍歷處理(規劃切片)目錄下的每一個文件。
(3)遍歷第一個文件ss.txt。
a)獲取文件大小fs.sizeOf(ss.txt);。
b)計算切片大小computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M。
c)默認情況下,切片大小=blocksize。
d)開始切,形成第1個切片:ss.txt—0:128M 第2個切片ss.txt—128:256M 第3個切片ss.txt—256M:300M(每次切片時,都要判斷切完剩下的部分是否大於塊的1.1倍,不大於1.1倍就劃分一塊切片)。
e)將切片信息寫到一個切片規劃文件中。
f)整個切片的核心過程在getSplit()方法中完成。
g)數據切片只是在邏輯上對輸入數據進行分片,並不會再磁盤上將其切分成分片進行存儲。InputSplit只記錄了分片的元數據信息,比如起始位置、長度以及所在的節點列表等。
h)注意:block是HDFS上物理上存儲的存儲的數據,切片是對數據邏輯上的劃分。
(4)提交切片規劃文件到yarn上,yarn上的MrAppMaster就可以根據切片規劃文件計算開啓maptask個數。
9、如何判定一個job的map和reduce的數量?
1)map數量
splitSize=max{minSize,min{maxSize,blockSize}}
map數量由處理的數據分成的block數量決定default_num = total_size / split_size;
2)reduce數量
reduce的數量job.setNumReduceTasks(x);x 爲reduce的數量。不設置的話默認爲 1。
10、 Maptask的個數由什麼決定?
一個job的map階段MapTask並行度(個數),由客戶端提交job時的切片個數決定。
11、MapTask和ReduceTask工作機制 (也可回答MapReduce工作原理)
MapTask工作機制
(1)Read階段:Map Task通過用戶編寫的RecordReader,從輸入InputSplit中解析出一個個key/value。
(2)Map階段:該節點主要是將解析出的key/value交給用戶編寫map()函數處理,併產生一系列新的key/value。
(3)Collect收集階段:在用戶編寫map()函數中,當數據處理完成後,一般會調用OutputCollector.collect()輸出結果。在該函數內部,它會將生成的key/value分區(調用Partitioner),並寫入一個環形內存緩衝區中。
(4)Spill階段:即“溢寫”,當環形緩衝區滿後,MapReduce會將數據寫到本地磁盤上,生成一個臨時文件。需要注意的是,將數據寫入本地磁盤之前,先要對數據進行一次本地排序,並在必要時對數據進行合併、壓縮等操作。
(5)Combine階段:當所有數據處理完成後,MapTask對所有臨時文件進行一次合併,以確保最終只會生成一個數據文件。
ReduceTask工作機制
(1)Copy階段:ReduceTask從各個MapTask上遠程拷貝一片數據,並針對某一片數據,如果其大小超過一定閾值,則寫到磁盤上,否則直接放到內存中。
(2)Merge階段:在遠程拷貝數據的同時,ReduceTask啓動了兩個後臺線程對內存和磁盤上的文件進行合併,以防止內存使用過多或磁盤上文件過多。
(3)Sort階段:按照MapReduce語義,用戶編寫reduce()函數輸入數據是按key進行聚集的一組數據。爲了將key相同的數據聚在一起,Hadoop採用了基於排序的策略。由於各個MapTask已經實現對自己的處理結果進行了局部排序,因此,ReduceTask只需對所有數據進行一次歸併排序即可。
(4)Reduce階段:reduce()函數將計算結果寫到HDFS上。
12、描述mapReduce有幾種排序及排序發生的階段
1)排序的分類:
(1)部分排序:
MapReduce根據輸入記錄的鍵對數據集排序。保證輸出的每個文件內部排序。
(2)全排序:
如何用Hadoop產生一個全局排序的文件?最簡單的方法是使用一個分區。但該方法在處理大型文件時效率極低,因爲一臺機器必須處理所有輸出文件,從而完全喪失了MapReduce所提供的並行架構。
替代方案:首先創建一系列排好序的文件;其次,串聯這些文件;最後,生成一個全局排序的文件。主要思路是使用一個分區來描述輸出的全局排序。例如:可以爲待分析文件創建3個分區,在第一分區中,記錄的單詞首字母a-g,第二分區記錄單詞首字母h-n, 第三分區記錄單詞首字母o-z。
(3)輔助排序:(GroupingComparator分組)
Mapreduce框架在記錄到達reducer之前按鍵對記錄排序,但鍵所對應的值並沒有被排序。甚至在不同的執行輪次中,這些值的排序也不固定,因爲它們來自不同的map任務且這些map任務在不同輪次中完成時間各不相同。一般來說,大多數MapReduce程序會避免讓reduce函數依賴於值的排序。但是,有時也需要通過特定的方法對鍵進行排序和分組等以實現對值的排序。
(4)二次排序:
在自定義排序過程中,如果compareTo中的判斷條件爲兩個即爲二次排序。
2)自定義排序WritableComparable
bean對象實現WritableComparable接口重寫compareTo方法,就可以實現排序
@Override
public int compareTo(FlowBean o) {
// 倒序排列,從大到小
return this.sumFlow > o.getSumFlow() ? -1 : 1;
}
3)排序發生的階段:
(1)一個是在map side發生在spill後partition前。
(2)一個是在reduce side發生在copy後 reduce前。
13、描述mapReduce中shuffle階段的工作流程,如何優化shuffle階段
分區,排序,溢寫,拷貝到對應reduce機器上,增加combiner,壓縮溢寫的文件。
14、描述mapReduce中combiner的作用是什麼,一般使用情景,哪些情況不需要,及和reduce的區別?
1)Combiner的意義就是對每一個maptask的輸出進行局部彙總,以減小網絡傳輸量。
2)Combiner能夠應用的前提是不能影響最終的業務邏輯,而且,Combiner的輸出kv應該跟reducer的輸入kv類型要對應起來。
3)Combiner和reducer的區別在於運行的位置。
Combiner是在每一個maptask所在的節點運行;
Reducer是接收全局所有Mapper的輸出結果。
15、如果沒有定義partitioner,那數據在被送達reducer前是如何被分區的?
如果沒有自定義的 partitioning,則默認的 partition 算法,即根據每一條數據的 key 的 hashcode 值摸運算(%)reduce 的數量,得到的數字就是“分區號“。
16、MapReduce 出現單點負載多大,怎麼負載平衡?
通過Partitioner實現
17、MapReduce 怎麼實現 TopN?
可以自定義groupingcomparator,對結果進行最大值排序,然後再reduce輸出時,控制只輸出前n個數。就達到了topn輸出的目的。
18、Hadoop的緩存機制(Distributedcache)
分佈式緩存一個最重要的應用就是在進行join操作的時候,如果一個表很大,另一個表很小,我們就可以將這個小表進行廣播處理,即每個計算節點上都存一份,然後進行map端的連接操作,經過我的實驗驗證,這種情況下處理效率大大高於一般的reduce端join,廣播處理就運用到了分佈式緩存的技術。
DistributedCache將拷貝緩存的文件到Slave節點在任何Job在節點上執行之前,文件在每個Job中只會被拷貝一次,緩存的歸檔文件會被在Slave節點中解壓縮。將本地文件複製到HDFS中去,接着Client會通過addCacheFile() 和addCacheArchive()方法告訴DistributedCache在HDFS中的位置。當文件存放到文地時,JobClient同樣獲得DistributedCache來創建符號鏈接,其形式爲文件的URI加fragment標識。當用戶需要獲得緩存中所有有效文件的列表時,JobConf 的方法 getLocalCacheFiles() 和getLocalArchives()都返回一個指向本地文件路徑對象數組。
19、如何使用mapReduce實現兩個表的join?
1)reduce side join : 在map階段,map函數同時讀取兩個文件File1和File2,爲了區分兩種來源的key/value數據對,對每條數據打一個標籤(tag),比如:tag=0 表示來自文件File1,tag=2 表示來自文件File2。
2)map side join : Map side join 是針對以下場景進行的優化:兩個待連接表中,有一個表非常大,而另一個表非常小,以至於小表可以直接存放到內存中。這樣,我們可以將小表複製多份,讓每個map task 內存中存在一份(比如存放到hash table 中),然後只掃描大表:對於大表中的每一條記錄key/value,在hash table 中查找是否有相同的key 的記錄,如果有,則連接後輸出即可。
20、什麼樣的計算不能用mr來提速?
1)數據量很小。
2)繁雜的小文件。
3)索引是更好的存取機制的時候。
4)事務處理。
5)只有一臺機器的時候。
21、ETL是哪三個單詞的縮寫
Extraction-Transformation-Loading的縮寫,中文名稱爲數據提取
、轉換
和加載
。
22、 HDFS 中的 block 默認保存幾份?
默認保存3份
23、HDFS 默認 BlockSize 是多大?
在Hadoop2.7版本之前是64MB,之後就改爲了128MB
24、負責HDFS數據存儲的是哪一部分?
DataNode負責數據存儲
25、SecondaryNameNode的目的是什麼?
他的目的使幫助NameNode合併編輯日誌,減少NameNode 二次啓動時間,備份數據
26、文件大小設置,增大有什麼影響?
HDFS中的文件在物理上是分塊存儲(block),塊的大小可以通過配置參數( dfs.blocksize)來規定,默認大小在hadoop2.x版本中是128M,老版本中是64M。
思考:爲什麼塊的大小不能設置的太小,也不能設置的太大?
HDFS的塊比磁盤的塊大,其目的是爲了最小化尋址開銷。如果塊設置得足夠大,從磁盤傳輸數據的時間會明顯大於定位這個塊開始位置所需的時間。因而,傳輸一個由多個塊組成的文件的時間取決於磁盤傳輸速率。
如果尋址時間約爲10ms,而傳輸速率爲100MB/s,爲了使尋址時間僅佔傳輸時間的1%,我們要將塊大小設置約爲100MB。默認的塊大小128MB。
塊的大小:10ms×100×100M/s = 100M 增加文件塊大小,需要增加磁盤的傳輸速率。
27、hadoop的塊大小,從哪個版本開始是128M
Hadoop1.x都是64M,hadoop2.x開始都是128M。
28、HDFS的存儲機制
HDFS存儲機制,包括HDFS的寫入數據過程和讀取數據過程兩部分
HDFS寫數據過程
1)客戶端通過Distributed FileSystem模塊向NameNode請求上傳文件,NameNode檢查目標文件是否已存在,父目錄是否存在。
2)NameNode返回是否可以上傳。
3)客戶端請求第一個 block上傳到哪幾個datanode服務器上。
4)NameNode返回3個datanode節點,分別爲dn1、dn2、dn3。
5)客戶端通過FSDataOutputStream模塊請求dn1上傳數據,dn1收到請求會繼續調用dn2,然後dn2調用dn3,將這個通信管道建立完成。
6)dn1、dn2、dn3逐級應答客戶端。
7)客戶端開始往dn1上傳第一個block(先從磁盤讀取數據放到一個本地內存緩存),以packet爲單位,dn1收到一個packet就會傳給dn2,dn2傳給dn3;dn1每傳一個packet會放入一個應答隊列等待應答。
8)當一個block傳輸完成之後,客戶端再次請求NameNode上傳第二個block的服務器。(重複執行3-7步)。
HDFS讀數據過程
1)客戶端通過Distributed FileSystem向NameNode請求下載文件,NameNode通過查詢元數據,找到文件塊所在的DataNode地址。
2)挑選一臺DataNode(就近原則,然後隨機)服務器,請求讀取數據。
3)DataNode開始傳輸數據給客戶端(從磁盤裏面讀取數據輸入流,以packet爲單位來做校驗)。
4)客戶端以packet爲單位接收,先在本地緩存,然後寫入目標文件。
29、secondary namenode工作機制
1)第一階段:NameNode啓動
(1)第一次啓動NameNode格式化後,創建fsimage和edits文件。如果不是第一次啓動,直接加載編輯日誌和鏡像文件到內存。
(2)客戶端對元數據進行增刪改的請求。
(3)NameNode記錄操作日誌,更新滾動日誌。
(4)NameNode在內存中對數據進行增刪改查。
2)第二階段:Secondary NameNode工作
(1)Secondary NameNode詢問NameNode是否需要checkpoint。直接帶回NameNode是否檢查結果。
(2)Secondary NameNode請求執行checkpoint。
(3)NameNode滾動正在寫的edits日誌。
(4)將滾動前的編輯日誌和鏡像文件拷貝到Secondary NameNode。
(5)Secondary NameNode加載編輯日誌和鏡像文件到內存,併合並。
(6)生成新的鏡像文件fsimage.chkpoint。
(7)拷貝fsimage.chkpoint到NameNode。
(8)NameNode將fsimage.chkpoint重新命名成fsimage。
30、NameNode與SecondaryNameNode 的區別與聯繫?
1)區別
(1)NameNode負責管理整個文件系統的元數據,以及每一個路徑(文件)所對應的數據塊信息。
(2)SecondaryNameNode主要用於定期合併命名空間鏡像和命名空間鏡像的編輯日誌。
2)聯繫:
(1)SecondaryNameNode中保存了一份和namenode一致的鏡像文件(fsimage)和編輯日誌(edits)。
(2)在主namenode發生故障時(假設沒有及時備份數據),可以從SecondaryNameNode恢復數據。
31、HDFS組成架構
架構主要由四個部分組成,分別爲HDFS Client、NameNode、DataNode和Secondary NameNode。下面我們分別介紹這四個組成部分。
1)Client:就是客戶端。
(1)文件切分。文件上傳HDFS的時候,Client將文件切分成一個一個的Block,然後進行存儲;
(2)與NameNode交互,獲取文件的位置信息;
(3)與DataNode交互,讀取或者寫入數據;
(4)Client提供一些命令來管理HDFS,比如啓動或者關閉HDFS;
(5)Client可以通過一些命令來訪問HDFS;
2)NameNode:就是Master,它是一個主管、管理者。
(1)管理HDFS的名稱空間;
(2)管理數據塊(Block)映射信息;
(3)配置副本策略;
(4)處理客戶端讀寫請求。
3)DataNode:就是Slave。NameNode下達命令,DataNode執行實際的操作。
(1)存儲實際的數據塊;
(2)執行數據塊的讀/寫操作。
4)Secondary NameNode:並非NameNode的熱備。當NameNode掛掉的時候,它並不能馬上替換NameNode並提供服務。
(1)輔助NameNode,分擔其工作量;
(2)定期合併Fsimage和Edits,並推送給NameNode;
(3)在緊急情況下,可輔助恢復NameNode。
32、HAnamenode 是如何工作的?
ZKFailoverController主要職責
1)健康監測:週期性的向它監控的NN發送健康探測命令,從而來確定某個NameNode是否處於健康狀態,如果機器宕機,心跳失敗,那麼zkfc就會標記它處於一個不健康的狀態。
2)會話管理:如果NN是健康的,zkfc就會在zookeeper中保持一個打開的會話,如果NameNode同時還是Active狀態的,那麼zkfc還會在Zookeeper中佔有一個類型爲短暫類型的znode,當這個NN掛掉時,這個znode將會被刪除,然後備用的NN,將會得到這把鎖,升級爲主NN,同時標記狀態爲Active。
3)當宕機的NN新啓動時,它會再次註冊zookeper,發現已經有znode鎖了,便會自動變爲Standby狀態,如此往復循環,保證高可靠,需要注意,目前僅僅支持最多配置2個NN。
4)master選舉:如上所述,通過在zookeeper中維持一個短暫類型的znode,來實現搶佔式的鎖機制,從而判斷那個NameNode爲Active狀態
33、MapReduce跑得慢的原因?
Mapreduce 程序效率的瓶頸在於兩點:
1)計算機性能
CPU、內存、磁盤健康、網絡
2)I/O 操作優化
(1)數據傾斜
(2)map和reduce數設置不合理
(3)reduce等待過久
(4)小文件過多
(5)大量的不可分塊的超大文件
(6)spill次數過多
(7)merge次數過多等
34、MapReduce優化方法
1)數據輸入
(1)合併小文件:在執行mr任務前將小文件進行合併,大量的小文件會產生大量的map任務,增大map任務裝載次數,而任務的裝載比較耗時,從而導致mr運行較慢。
(2)採用ConbinFileInputFormat來作爲輸入,解決輸入端大量小文件場景。
2)map階段
(1)減少spill次數:通過調整io.sort.mb及sort.spill.percent參數值,增大觸發spill的內存上限,減少spill次數,從而減少磁盤 IO。
(2)減少merge次數:通過調整io.sort.factor參數,增大merge的文件數目,減少merge的次數,從而縮短mr處理時間。
(3)在 map 之後先進行combine處理,減少I/O。
3)reduce階段
(1)合理設置map和reduce數:兩個都不能設置太少,也不能設置太多。太少,會導致task等待,延長處理時間;太多,會導致 map、reduce任務間競爭資源,造成處理超時等錯誤。
(2)設置map、reduce共存:調整slowstart.completedmaps參數,使map運行到一定程度後,reduce也開始運行,減少reduce的等待時間。
(3)規避使用reduce,因爲Reduce在用於連接數據集的時候將會產生大量的網絡消耗。
(4)合理設置reduce端的buffer,默認情況下,數據達到一個閾值的時候,buffer中的數據就會寫入磁盤,然後reduce會從磁盤中獲得所有的數據。也就是說,buffer和reduce是沒有直接關聯的,中間多個一個寫磁盤->讀磁盤的過程,既然有這個弊端,那麼就可以通過參數來配置,使得buffer中的一部分數據可以直接輸送到reduce,從而減少IO開銷:mapred.job.reduce.input.buffer.percent,默認爲0.0。當值大於0的時候,會保留指定比例的內存讀buffer中的數據直接拿給reduce使用。這樣一來,設置buffer需要內存,讀取數據需要內存,reduce計算也要內存,所以要根據作業的運行情況進行調整。
4)IO傳輸
(1)採用數據壓縮的方式,減少網絡IO的的時間。安裝Snappy和LZOP壓縮編碼器。
(2)使用SequenceFile二進制文件
5)數據傾斜問題
(1)數據傾斜現象 數據頻率傾斜——某一個區域的數據量要遠遠大於其他區域。
數據大小傾斜——部分記錄的大小遠遠大於平均值。
(2)如何收集傾斜數據
在reduce方法中加入記錄map輸出鍵的詳細情況的功能。
public static final String MAX_VALUES = "skew.maxvalues";
private int maxValueThreshold;
@Override
public void configure(JobConf job) {
maxValueThreshold = job.getInt(MAX_VALUES, 100);
}
@Override
public void reduce(Text key, Iterator<Text> values,
OutputCollector<Text, Text> output,
Reporter reporter) throws IOException {
int i = 0;
while (values.hasNext()) {
values.next();
i++;
}
if (++i > maxValueThreshold) {
log.info("Received " + i + " values for key " + key);
}
}
(3)減少數據傾斜的方法
方法1:抽樣和範圍分區
可以通過對原始數據進行抽樣得到的結果集來預設分區邊界值。
方法2:自定義分區
另一個抽樣和範圍分區的替代方案是基於輸出鍵的背景知識進行自定義分區。例如,如果map輸出鍵的單詞來源於一本書。其中大部分必然是省略詞(stopword)。那麼就可以將自定義分區將這部分省略詞發送給固定的一部分reduce實例。而將其他的都發送給剩餘的reduce實例。
方法3:Combine
使用Combine可以大量地減小數據頻率傾斜和數據大小傾斜。在可能的情況下,combine的目的就是聚合並精簡數據。
35、HDFS小文件優化方法
1)HDFS小文件弊端:
HDFS上每個文件都要在namenode上建立一個索引,這個索引的大小約爲150byte,這樣當小文件比較多的時候,就會產生很多的索引文件,一方面會大量佔用namenode的內存空間,另一方面就是索引文件過大是的索引速度變慢。
2)解決的方式:
(1)Hadoop本身提供了一些文件壓縮的方案。 (2)從系統層面改變現有HDFS存在的問題,其實主要還是小文件的合併,然後建立比較快速的索引。
3)Hadoop自帶小文件解決方案
(1)Hadoop Archive:
是一個高效地將小文件放入HDFS塊中的文件存檔工具,它能夠將多個小文件打包成一個HAR文件,這樣在減少namenode內存使用的同時。
(2)Sequence file:
sequence file由一系列的二進制key/value組成,如果爲key小文件名,value爲文件內容,則可以將大批小文件合併成一個大文件。
(3)CombineFileInputFormat:
CombineFileInputFormat是一種新的inputformat,用於將多個文件合併成一個單獨的split,另外,它會考慮數據的存儲位置。
36、簡述hadoop1與hadoop2 的架構異同
1)加入了yarn解決了資源調度的問題。
2)加入了對zookeeper的支持實現比較可靠的高可用。
37、爲什麼會產生 yarn,它解決了什麼問題,有什麼優勢?
1)Yarn最主要的功能就是解決運行的用戶程序與yarn框架完全解耦。
2)Yarn上可以運行各種類型的分佈式運算程序(mapreduce只是其中的一種),比如mapreduce、storm程序,spark程序……
38、HDFS的數據壓縮算法?
Hadoop中常用的壓縮算法有bzip2、gzip、lzo、snappy,其中lzo、snappy需要操作系統安裝native庫纔可以支持。
數據可以壓縮的位置如下所示。
企業開發用的比較多的是snappy。
39、Hadoop的調度器總結
(1)默認的調度器FIFO
Hadoop中默認的調度器,它先按照作業的優先級高低,再按照到達時間的先後選擇被執行的作業。
(2)計算能力調度器Capacity Scheduler
支持多個隊列,每個隊列可配置一定的資源量,每個隊列採用FIFO調度策略,爲了防止同一個用戶的作業獨佔隊列中的資源,該調度器會對同一用戶提交的作業所佔資源量進行限定。調度時,首先按以下策略選擇一個合適隊列:計算每個隊列中正在運行的任務數與其應該分得的計算資源之間的比值,選擇一個該比值最小的隊列;然後按以下策略選擇該隊列中一個作業:按照作業優先級和提交時間順序選擇,同時考慮用戶資源量限制和內存限制。
(3)公平調度器Fair Scheduler
同計算能力調度器類似,支持多隊列多用戶,每個隊列中的資源量可以配置,同一隊列中的作業公平共享隊列中所有資源。實際上,Hadoop的調度器遠不止以上三種,最近,出現了很多針對新型應用的Hadoop調度器。
40、MapReduce 2.0 容錯性
1)MRAppMaster容錯性
一旦運行失敗,由YARN的ResourceManager負責重新啓動,最多重啓次數可由用戶設置,默認是2次。一旦超過最高重啓次數,則作業運行失敗。
2)Map Task/Reduce
Task Task週期性向MRAppMaster彙報心跳;一旦Task掛掉,則MRAppMaster將爲之重新申請資源,並運行之。最多重新運行次數可由用戶設置,默認4次。
41、mapreduce推測執行算法及原理
1)作業完成時間取決於最慢的任務完成時間
一個作業由若干個Map 任務和Reduce 任務構成。因硬件老化、軟件Bug 等,某些任務可能運行非常慢。
典型案例:系統中有99%的Map任務都完成了,只有少數幾個Map老是進度很慢,完不成,怎麼辦?
2)推測執行機制
發現拖後腿的任務,比如某個任務運行速度遠慢於任務平均速度。爲拖後腿任務啓動一個備份任務,同時運行。誰先運行完,則採用誰的結果。
3)不能啓用推測執行機制情況
(1)任務間存在嚴重的負載傾斜;
(2)特殊任務,比如任務向數據庫中寫數據。
4)算法原理
假設某一時刻,任務T的執行進度爲progress,則可通過一定的算法推測出該任務的最終完成時刻estimateEndTime。另一方面,如果此刻爲該任務啓動一個備份任務,則可推斷出它可能的完成時刻estimateEndTime,於是可得出以下幾個公式:
estimateEndTime=estimatedRunTime+taskStartTime
estimatedRunTime=(currentTimestamp-taskStartTime)/progress
estimateEndTime= currentTimestamp+averageRunTime
其中,currentTimestamp爲當前時刻;taskStartTime爲該任務的啓動時刻;averageRunTime爲已經成功運行完成的任務的平均運行時間。這樣,MRv2總是選擇(estimateEndTime- estimateEndTime·)差值最大的任務,併爲之啓動備份任務。爲了防止大量任務同時啓動備份任務造成的資源浪費,MRv2爲每個作業設置了同時啓動的備份任務數目上限。
推測執行機制實際上採用了經典的算法優化方法:以空間換時間,它同時啓動多個相同任務處理相同的數據,並讓這些任務競爭以縮短數據處理時間。顯然,這種方法需要佔用更多的計算資源。在集羣資源緊缺的情況下,應合理使用該機制,爭取在多用少量資源的情況下,減少作業的計算時間。
本文分享自微信公衆號 - 大數據技術與架構(import_bigdata)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。