MapReduce 詳解與原始碼分析
1 Split 階段
在 mapreduce 中的 map task 開始之前,將檔案按照指定的大小切割成若干個部分,每一部分稱為一個 split,預設是 split 的大小與 block 的大小相等,均為 128MB。split 大小由 minSize、maxSize、blocksize 決定,以 wordcount 程式碼為例,以下是 main()方法
這其中又分為兩部分:確定切片數量 和 寫入切片資訊。確定切片數量的任務交由 FileInputFormat 的 getSplits(job)完成,寫入切片資訊的任務交由 JobSplitWriter.createSplitFiles(jobSubmitDir, conf, jobSubmitDir.getFileSystem(conf), array)方法,該方法會將切片資訊和 SplitMetaInfo 都寫入 HDFS 中。
return array.length;
返回的是 map 任務數,
預設 map 的數量是:
default_num = total_size / block_size;
實際的 mapper 數量就是輸入切片的數量,而切片的數量又由使用的輸入格式決定,預設為 TextInputFormat,該類為 FileInputFormat 的子類。
確定切片數量的任務交由 FileInputFormat 的 getSplits(job)完成。FileInputFormat 繼承自抽象類 InputFormat,該類定義了 MapReduce 作業的輸入規範,其中的抽象方法 List getSplits(JobContext context)定義瞭如何將輸入分割為 InputSplit,不同的輸入有不同的分隔邏輯,而分隔得到的每個 InputSplit 交由不同的 mapper 處理,因此該方法的返回值確定了 mapper 的數量。
2 Map 階段
每個 map task 都有一個記憶體緩衝區, map 的輸出結果先寫到記憶體中的環形緩衝區,緩衝區為 100M,不斷的向緩衝區力寫資料,當達到 80M 時,需要將緩衝區中的資料以一個臨時檔案的方式存到磁碟,當整個 map task 結束後再對磁碟中這個 map task 所產生的所有臨時檔案做合併,生成最終的輸出檔案。
最後,等待 reduce task 來拉取資料。當然,如果 map task 的結果不大,能夠完全儲存到記憶體緩衝區,且未達到記憶體緩衝區的閥值,那麼就不會有寫臨時檔案到磁碟的操作,也不會有後面的合併。在寫入的過程中會進行分割槽、排序、combine 操作。
環形緩衝區:是使用指標機制把記憶體中的地址首尾相接形成一個儲存中間資料的快取區域,預設 100MB;80M 閾值,20M 緩衝區,是為了解決寫入環形緩衝區資料的速度大於寫出到 spill 檔案的速度是資料的不丟失;Spill 檔案:spill 檔案是環形緩衝區到達閾值後寫入到磁碟的單個檔案.這些檔案在 map 階段計算結束時,會合成分好區的一個 merge 檔案供給給 reduce 任務抓取;spill 檔案過小的時候,就不會浪費 io 資源合併 merge;預設情況下 3 個以下 spill 檔案不合並;對於在環形緩衝區中的資料,最終達不到 80m 但是資料已經計算完畢的情況,map 任務將會呼叫 flush 將緩衝區中的資料強行寫出 spill 檔案。
按照 key 合併成大檔案,減少網路開銷
2.1 分割槽
假設有聽個 reduce 任務,則分割槽的計算如下:
2.2 排序
3 Shuffle 階段
4 Reduce 階段
2 抓取過來的資料會先儲存在記憶體中,如果記憶體過大也溢位,不可見,不可調,但是單位是每個 merge 檔案,不會切分資料;每個 merge 檔案都會被封裝成一個 segment 的物件,這個物件控制著這個 merge 檔案的讀取記錄操作,有兩種情況出現:在記憶體中有 merge 資料 •在溢寫之後存到磁碟上的資料 •透過建構函式的區分,來分別建立對應的 segment 物件
3 這種 segment 物件會放到一個記憶體佇列中 MergerQueue,對記憶體和磁碟上的資料分別進行合併,記憶體中的 merge 對應的 segment 直接合並,磁碟中的合併與一個叫做合併因子的 factor 有關(預設是 10)
排序問題,MergerQueue 繼承輪換排序的介面,每一個 segment 是排好序的,而且按照 key 的值大小邏輯(和真的大小沒關係);每一個 segment 的第一個 key 都是邏輯最小,而所有的 segment 的排序是按照第一個 key 大小排序的,最小的在前面,這種邏輯總能保證第一個 segment 的第一個 key 值是所有 key 的邏輯最小檔案合併之後,最終交給 reduce 函式計算的,是 MergeQueue 佇列,每次計算的提取資料邏輯都是提取第一個 segment 的第一個 key 和 value 資料,一旦 segment 被呼叫了提取 key 的方法,MergeQueue 佇列將會整體重新按照最小 key 對 segment 排序,最終形成整體有序的計算結果;
Reduce 任務數量 在大資料量的情況下,如果只設定 1 個 Reduce 任務,其他節點將被閒置,效率底下 所以將 Reduce 設定成一個較大的值(max:72).調節 Reduce 任務數量的方法 一個節點的 Reduce 任務數並不像 Map 任務數那樣受多個因素制約
參考博文:
https://gitchat.blog.csdn.net/article/details/104190423?spm=1001.2101.3001.6650.7&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-7-104190423-blog-81115646.pc_relevant_multi_platform_whitelistv4&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-7-104190423-blog-81115646.pc_relevant_multi_platform_whitelistv4&utm_relevant_index=8
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69949806/viewspace-2915687/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- LeakCanary詳解與原始碼分析原始碼
- Mapreduce Job提交流程原始碼和切片原始碼詳解原始碼
- ArrayList詳解-原始碼分析原始碼
- Mapreduce原始碼分析分片、處理流程原始碼
- LinkedList詳解-原始碼分析原始碼
- ArrayMap詳解及原始碼分析原始碼
- EventBus詳解及原始碼分析原始碼
- Android原始碼分析--CircleImageView 原始碼詳解Android原始碼View
- Hadoop2原始碼分析-MapReduce篇Hadoop原始碼
- MapReduce——客戶端提交任務原始碼分析客戶端原始碼
- MapReduce —— MapTask階段原始碼分析(Input環節)APT原始碼
- MapReduce —— MapTask階段原始碼分析(Output環節)APT原始碼
- mapreduce job提交流程原始碼級分析(三)原始碼
- MapReduce框架Mapper和Reducer類原始碼分析框架APP原始碼
- mapreduce框架詳解框架
- Linuxepoll模型詳解及原始碼分析Linux模型原始碼
- MapReduce job在JobTracker初始化原始碼級分析原始碼
- MapReduce過程詳解
- mapreduce job提交流程原始碼級分析(二)(原創)原始碼
- 詳解Java 容器(第③篇)——容器原始碼分析 - ListJava原始碼
- 詳解Java 容器(第④篇)——容器原始碼分析 - MapJava原始碼
- Django模型驗證器詳解和原始碼分析Django模型原始碼
- React原始碼分析3—React生命週期詳解React原始碼
- Tomcat詳解系列(3) - 原始碼分析準備和分析入口Tomcat原始碼
- redux 原始碼詳解Redux原始碼
- TimSort原始碼詳解原始碼
- HashMap原始碼詳解HashMap原始碼
- HashSet原始碼詳解原始碼
- ProgressHUD原始碼詳解原始碼
- 【UGUI原始碼分析】Unity遮罩之Mask詳細解讀UGUI原始碼Unity遮罩
- JDK動態代理實現原理詳解(原始碼分析)JDK原始碼
- MapReduce 二次排序詳解排序
- 【Redis原始碼】Redis 6 ACL原始碼詳解Redis原始碼
- LinkedHashMap原始碼詳解HashMap原始碼
- 詳解Java 容器(第⑤篇)——容器原始碼分析 - 併發容器Java原始碼
- Spring原始碼分析之Bean的建立過程詳解Spring原始碼Bean
- Netty原始碼分析之Reactor執行緒模型詳解Netty原始碼React執行緒模型
- Spring原始碼分析之spring-jms模組詳解Spring原始碼