• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • MR切片機制總結

    標簽: Hadoop3  mapreduce  大數據  hadoop  

    MR切片機制總結

    一、概述

    MR程序在運行的時候需要將文件切分為多個分發給不同MapTask進行處理,那么問題來了,MR底層是如何對文件進行切分的呢?

    二、InputFormat切片機制

    1. Hadoop框架內部定義了一個讀取數據的基類流~InputFormat(抽象類),其內部定義了2個抽象方法
      快捷鍵Ctrl + N 搜索InputFormat類,查看該類中方法
    public abstract class InputFormat<K, V> {
    	public abstract List<InputSplit> getSplits(JobContext context);	//生成切片,對數據切分
    	public abstract RecordReader<K,V> createRecordReader(InputSplit 	split,TaskAttemptContext context);		//創建RecordReader對象,真正負責數據讀取的對象.
    	==>真實按行讀取是TextInputFormat類中的RecordReader()方法		//--67行
    }
    
    1. 我們查看InputFormat的具體實現類
      快捷鍵Ctrl + H 查看InputFormat類體系~~~查看具體實現類FileInputFormat(子抽象類)
    1. FileInputFormat中對getSplits()方法做出了具體實現. --389行
      createRecordReader()方法未作任何改變。 --直接定位到父類中的該方法
      isSplitable()方法:判斷當前輸入的數據是否可切分,默認true. --169行
      該方法具體實現是在TextInputFormat中的isSplitable()方法,主要針對的是壓縮文件

    在這里插入圖片描述

    1. FileInputFormat是子抽象類,我們看下其具體的實現類,見 上圖
      我們需要掌握的是TextInputFormat和CombineTextInputFormat
      TextInputFormat是MapReduce默認使用的讀取數據的類
      比如:WordCount和Flow案例使用的均是TextInputFormat完成數據輸入的
      CombineTextInputFormat用于小文件過多的場景,它可以將多個小文件從邏輯上規劃到一個切片中,這樣,多個小文件就可以交給一個MapTask處理,內部改寫了切片規則(用來處理小文件過多造成啟動多個MapTask運行處理很小的數據量的情況)

    三、切片設置

    1. 塊:HDFS存儲數據的單位,指把要存儲到HDFS文件系統上的文件以設置好的塊的大小進行物理切分成N個塊(真正的將數據切割)
    2. 切片:MapReduce計算數據的單位,指把要在MR中計算的數據從邏輯上按照設置的切片大小,劃分為N個切片
    • 示例:
      比如現有一個200M的文件,要讀取到MR程序中做運算,假設設置切片大小為100M,那么,邏輯上是將200M的數據切為
      0-100M,100-200M兩個切片,真實并沒有將200M的數據進行切分,200M的文件數據依然保持完整。
      生成的切片記錄的是:第一個切片文件從0位置讀到100M位置 ,第二個切片從100M讀取到200M的位置
      即記錄讀數據的時候,從什么位置讀取到什么位置。
    1. 切片大小設置
      切片的大小設置并不是隨意設置的,要和塊的設置大小關聯起來
    • 比如,現在對一個200M的文件進行操作,上傳到HDFS系統,分為0-128M,128-200M兩個塊,那么假設存儲到DN節點上就是dn1存儲128M,dn2存儲72M,我們希望當MR程序讀取數據做運算時,MR可以一次性將節點上的數據讀完或者保證一個MapTask只在一個節點上讀數據(因為一個切片數據交給一個MapTask處理),所以綜合考慮,我們應該將切片大小設置成和塊大小一致。
    • 默認:將切片大小設置成==block塊大小,避免MR程序讀取數據時,出現跨節點讀取。

    四、切片源碼解讀

    //1、getSplits()方法源碼解析:
    /*
    getFormatMinSplitSize() :1
    getMinSplitSize(job) :
    	如果設置mapreduce.input.fileinputformat.split.minsize那么就使用設置的值,如果沒有設置
    	默認是1
    */
    long minSize = Math.max(getFormatMinSplitSize(), getMinSplitSize(job));
    
    /*
    如果在Configuration中配置了如下內容的值
    	mapreduce.input.fileinputformat.split.maxsize那么獲取的就是配置的值。
    	如果沒有配置那么默認值是Long.MAX_VALUE
    */
    long maxSize = getMaxSplitSize(job);		
    
    //最終將生成的切片放入到splits集合中. 
    List<InputSplit> splits = new ArrayList<InputSplit>();		
    //獲取存儲文件的詳情		
    List<FileStatus> files = listStatus(job); 
    //遍歷files		
    for (FileStatus file: files) {	
    	  //判斷file是否是文件夾				
          if (ignoreDirs && file.isDirectory()) {	
            continue;
          }
    //獲取文件路徑
    Path path = file.getPath();	
    //獲取文件長度					
    long length = file.getLen();	
    //判斷文件是否可切分				
    if (isSplitable(job, path)) {	
    	//獲取文件的塊大小				
    	long blockSize = file.getBlockSize();     
    	//如果是集群環境,獲取到的就是集群中設置的塊大小,如果是本地環境,本地默認的塊大小32M (33554432)
    	//計算切片大小
    	long splitSize = computeSplitSize(blockSize, minSize, maxSize);		
    	
    		//查看computeSplitSize()方法
    		protected long computeSplitSize(long blockSize, long minSize,long maxSize) {
    				/*
    					默認塊大小=切片大小
    					設置:
    						切片大小 < 塊大小:修改maxSize的值
    						切片大小 > 塊大小:修改minSize的值
    				*/
    				return Math.max(minSize, Math.min(maxSize, blockSize));
    			}
    }
    
    //文件的剩余大小
    long bytesRemaining = length;					
    //只有當剩余文件大小 / 切片大下 其值 > 1.1 時,才會進行切片操作
    while (((double) bytesRemaining)/splitSize > SPLIT_SLOP) {		
    	//計算切片時如何去切
       int blkIndex = getBlockIndex(blkLocations, length-bytesRemaining);
       /*
    		splits :用來存儲切片信息的集合
    		makeSplit : 用來生成切片信息
    		length-bytesRemaining : 切片的起始位置
    		splitSize :切片的偏移量(長度)
    	*/
       splits.add(makeSplit(path, length-bytesRemaining, splitSize,
       		  blkLocations[blkIndex].getHosts(),			//記錄的是讀取那個文件
              blkLocations[blkIndex].getCachedHosts()));	//從文件那個位置讀取到那個位置
              //重新計算剩余文件的大小
       		  bytesRemaining -= splitSize;	
    }
    
    
    //把剩余文件大小/splitSize <= 1.1 把滿足此條件的剩余文件切成一片 
    if (bytesRemaining != 0) {
    	int blkIndex = getBlockIndex(blkLocations, length-bytesRemaining);
    	/*
    		splits :用來存儲切片信息的集合
    		makeSplit : 用來生成切片信息
    			length-bytesRemaining : 切片的起始位置
    			bytesRemaining :切片的偏移量(長度)
    	*/
    	splits.add(makeSplit(path, length-bytesRemaining, bytesRemaining,
    			   blkLocations[blkIndex].getHosts(),
    			   blkLocations[blkIndex].getCachedHosts()));
    }
    
     
    

    結論:

    1. 如果剩余待切片的數據大小 除以 塊大小,大于1.1 ,才會繼續切片,如果不大于,則直接將剩余的數據 生成一個切片.
    2. 真實切片時,是完全按照塊大小進行切的,只是針對剩余數據是否仍要切片時,會有一個大于1.1的判斷,要做上述判斷,避免生成很小的切片,節省MapTask資源
    3. 切片大小默認等于Block大小128M,避免MR程序讀取數據時,出現跨節點讀取,節省資源。
    4. 每個切片都需要由一個MapTask來處理 , 也就意味著在一個MR中,有多少個切片,就會有多少個MapTask。
    5. 切片的時候每個文件單獨切片,不會整體切片.(完全基于單個文件)
    6. 切片的個數不是越多越好,也不是越少越好,按照實際情況,處理成合適的切片數.

    五、CombineTextInputFormat~切片機制

    CombineTextInputFormat解決的問題:
    用于小文件過多的場景,它可以將多個小文件從邏輯上規劃到一個切片中,這樣,多個小文件就可以交給一個MapTask處理。

    核心操作:設置虛擬切片最大值
    在Driver中設置
    job.setInputFormatClass(CombineTextInputFormat.class); --不設置,默認是FileInputFormat
    CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 假設設置為4M

    1、如果文件的大小小于MaxInputSplitSize , 則文件規劃成一個
    2、如果文件的大小 大于MaxInputSplitSize ,但是小于 MaxInputSplitSize2 , 則文件規劃成兩個(對半分)
    3、如果文件的大小大于 MaxInputSplitSize
    2 ,先按照MaxInputSplitSize的大小規劃一個, 剩余的再進行規劃.
    4、最終按照 MaxInputSplitSize 大小來生成切片,
    5、將規劃好的每個虛擬文件逐個累加,只要不超過 MaxInputSplitSize大小,則都是規劃到一個切片中的。

    舉例:
    有4個小文件大小分別為1.7M、5.1M、3.4M以及6.8M這四個小文件
    則虛擬存儲之后形成6個文件塊,大小分別為:1.7M,(2.55M、2.55M),3.4M以及(3.4M、3.4M)
    基于虛擬存儲,最終會形成3個切片,大小分別為:(1.7+2.55)M,(2.55+3.4)M,(3.4+3.4)M

    基礎鏈接:
    MapReduce核心思想: https://blog.csdn.net/weixin_42796403/article/details/109732859
    手寫MR程序之wordcount案例: https://blog.csdn.net/weixin_42796403/article/details/109749080
    Hadoop切片與MapTask并行度決定機制: https://blog.csdn.net/weixin_42796403/article/details/109753044
    MR核心編程思想總結: https://blog.csdn.net/weixin_42796403/article/details/109802287
    FileInputFormat切片源碼解析: https://blog.csdn.net/weixin_42796403/article/details/109804581
    CombineTextInputFormat切片機制: https://blog.csdn.net/weixin_42796403/article/details/109806713
    TextInputFormat切片機制: https://blog.csdn.net/weixin_42796403/article/details/109811157

    版權聲明:本文為weixin_42796403原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/weixin_42796403/article/details/109811966

    智能推薦

    MapReduce之InputFormat切片機制及讀取數據模式

    MapReduce之InputFormat 體系結構 InputFormat FileInputFormat TextInputFormat CombineFileInputFormat NLineInputFormat KeyValueTextInputFormat 體系結構 InputFormat 有getSplits(JobContext var1)和createRecordReader(I...

    MapReduce框架原理—InputFormat數據輸入(源碼詳解+實現類+切片機制+案例操作)

    一、Job提交流程和切片源碼詳解 1.job提交流程源碼詳解,如代碼下圖 2.FileInputFormat源碼解析(input.getSplits(job)) (1)找到你數據存儲的目錄。 (2)開始遍歷處理(規劃切片)目錄下的每一個文件 (3)遍歷第一個文件ss.txt   a)獲取文件大小fs.sizeOf(ss.txt)   b)計算切片大小 &em...

    神奇的Batch Normalization 如果一個模型僅訓練BN層會是什么樣的

    您可能會感到驚訝,但這是有效的。 ? 最近,我閱讀了arXiv平臺上的Jonathan Frankle,David J. Schwab和Ari S. Morcos撰寫的論文“Training BatchNorm and Only BatchNorm: On the Expressive Power of Random Features in CNNs”。 這個主意立刻引起了...

    用Python實現校園通知更新提醒

    前言 這個項目實已經在一個月前已經完成了,一直都想寫一篇博客來總結這個過程中遇到的一些問題。但最近一個月來都比較忙,所以一直拖到了現在。 首先說說起因吧,我沒事的時候,總喜歡依次點開學校主頁、教務處、圖書館以及學院的網站,看看有沒有什么新通知,雖然大多與我無關。恰逢最近正在學Python,經常聽到別人說用Python寫爬蟲很簡單,但自己尚未接觸過爬蟲。于是抱著試一試的心態看了幾篇關于Python爬...

    spring_ioc相關_第一章

    1 spring是一站式框架,在javaee的三層結構中,每一層都提供不提并的解決技術 web層:springMVC service層:spring的ioc dao層:spring的jdbcTemplate 2 javaee為避免兩個類之間出現耦合,則把對象的創建交給spring進行管理,spring的ioc操作:(1)ioc的配置文件方式;(2)ioc注解方式 3 ioc的底層原理使用技術(1)...

    猜你喜歡

    【Python+OpenCV】視頻流局部區域像素值處理-一種特征提取方法

    參考我之前寫的處理圖片的文章:Python+OpenCV實現【圖片】局部區域像素值處理(改進版) 開發環境:Python3.6.0 + OpenCV3.2.0 任務目標:攝像頭采集圖像(例如:480*640),并對視頻流每一幀(灰度圖)特定矩形區域(480*30)像素值進行行求和,得到一個480*1的數組,用這480個數據繪制條形圖,即在逐幀采集視頻流并處理后“實時”顯示采...

    JavaWeb——【前端】——注冊頁面

    頁面效果 實現代碼 注意事項 主要使用的bootstrap樣式 如果想引用,不要直接復制,沒用的。 先介紹下所引用的文件: boostrap的js、bootstrap的css、jquery的js、以及自己編寫的register.css。 因為博主用的thymeleaf語法,所以有th符號。 若要使用時,根據個人情況導入相應的依賴。...

    網站HTTP升級HTTPS完全配置手冊

    本文由葡萄城技術團隊于博客園原創并首發 轉載請注明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。 今天,所有使用Google Chrome穩定版的用戶迎來了v68正式版首個版本的發布,詳細版本號為v68.0.3440.75,上一個正式版v67.0.3396.99發布于6月13日,自Chrome 68起,當在加載非HTTPS站點時,都會在地址欄上明確標記為&ldqu...

    echarts 自定義儀表盤設置背景圖片

    echarts儀表盤 使用插件 vue-echarts 代碼示例 HTML部分 js部分 效果圖...

    RT-Thread Studio部分定時器時鐘不正確的解決方案

    在昨天的RT-Thread Studio硬件定時器hwtimer在stm32f411上的使用筆記中,遇到了部分定時器速度想象中和實際不一致的情況,具體表現在定時器2、3、4、5、9、10、11都正常,但定時器1要快一倍。 仔細查看代碼,找到了原因。 因為代碼使用的是工程是直接生成的時鐘代碼,實際的時鐘頻率是這樣的: 而實際的定時器時鐘配置代碼如下: 針對F411,去掉其中的宏定義是這樣的: 這里說...

    精品国产乱码久久久久久蜜桃不卡