前言
- 據說,自0.20.0版本開始,Hadoop同時提供了新舊兩套MapReduce API,並在後續版本中也同時支持這兩種API的使用。新版本MR API在舊的基礎進行了擴展,也制定了新的split計算方式。新版本MR API在包org.apache.hadoop.mapreduce及其子包中,而舊版本MR API則在包org.apache.hadoop.mapred及其子包中。
- 本文主要從源碼角度,簡單談談新舊MR API中常用的FileInputFormat類(TextInputFormat的父類)中分片Split的計算方式,可以以此來確定每次MR的Mapper個數,默認情況下Mapper的個數即等於分片Split個數。
新舊MapReduce API的作業配置方式對比
舊API 作業配置實例:
JobConf job = new JobConf(new Configuration(), MyJob.class);
job.setJobName("myjob");
job.setMapperClass(MyJob.MyMapper.class);
job.setReducerClass(MyJob.MyReducer.class);
JobClient.runJob(job);
新API 作業配置實例:
Configuration conf = new Configuration();
Job job = new Job(conf, "myjob ");
job.setJarByClass(MyJob.class);
job.setMapperClass(MyJob.MyMapper.class);
job.setReducerClass(MyJob.MyReducer.class);
System.exit(job.waitForCompletion(true) ? 0 : 1);
分片Split計算過程
在提交MR Job時,Job在setUseNewAPI
方法中根據設置的Mapper類來確定設置參數"mapred.mapper.new-api"
的值,如果是使用的是舊版API,則此參數爲false,否則爲true;
然後JobSubmitter會根據參數"mapred.mapper.new-api"
的值來判斷,是使用舊版還是新版API中的getSplits
方法來確定分片Split。
分片Split計算公式
由上一節圖可知,最終SplitSize的計算,在舊版本API中由org.apache.hadoop.mapred.InputFormat#getSplits
方法決定,在新版本API中由org.apache.hadoop.mapreduce.InputFormat#getSplits
方法決定。
舊版本FileInputFormat中分片大小splitsSize計算公式
通過查看org.apache.hadoop.mapred.FileInputFormat中的getSplits方法,可以得出對應的SplitSize計算公式:
Math.max(minSize,Math.min(goalSize,blockSize))
PS:
goalSize
等於所有輸入文件的總大小除以參數"mapreduce.job.maps"
的值(此參數默認值爲1,可以在 mapred-site.xml 文件中配置);
blockSize
指的是當前文件在HDFS中存儲時的BLOCK大小(可以通過在 hdfs-site.xml 文件中設置"dfs.block.size"
或者"dfs.blocksize"
參數來調整之後新生成的HDFS文件BLOCK大小);
minSize
爲參數"mapreduce.input.fileinputformat.split.minsize"
的值(此參數默認值爲1,可以在 mapred-site.xml 文件中配置)。
新版本FileInputFormat中分片大小splitsSize計算公式
通過查看org.apache.hadoop.mapreduce.lib.input.FileInputFormat中的getSplits方法,可以得出對應的SplitSize計算公式:
Math.max(minSize,Math.min(maxSize,blockSize))
PS:
minSize
等於參數"mapreduce.input.fileinputformat.split.minsize"
的值(此參數默認值爲1,可以在 mapred-site.xml 文件中配置);
maxSize
爲參數"mapreduce.input.fileinputformat.split.maxsize"
的值(此參數默認值爲Long.MAX_VALUE
,即0x7fffffffffffffffL,可以在 mapred-site.xml 文件中配置);
blockSize
指的是當前文件在DFS中存儲時的BLOCK大小(可以通過在 hdfs-site.xml 文件中設置"dfs.block.size"
或者"dfs.blocksize"
參數來調整之後新生成文件的BLOCK大小)。
分片規則
當一個文件的剩餘未分片大小除以splitSize大於1.1(即超過splitSize的10%)時,則認爲文件大小“溢出”,需要切割分成多個分片,每切割一次,剩餘未分片大小減少splitSize;否則則將整個剩餘未分片的內容作爲單個分片。
FileInputFormat分片數量計算
對於輸入路徑中的每個文件都應用split分片規則來對其進行分片,每個文件至少切成一個Split(如果文件內容爲空,大小爲0,則創建空分片Split)。
Mapper個數的確定
默認情況下,Mapper的個數即等於最終的分片個數
舊版本API:
可以通過修改"mapreduce.job.maps"
、"mapreduce.input.fileinputformat.split.minsize"
、"dfs.blocksize"
參數來調整分片大小splitSize來調整最終分片個數,進而調整Mapper數量。
根據舊版API中splitSize計算公式,當goalSize小於blockSize,大於minSize時,Mapper數量大致等於參數"mapreduce.job.maps"
的值。
新版本API:
可以通過修改"mapreduce.input.fileinputformat.split.minsize"
、"mapreduce.input.fileinputformat.split.maxsize"
、"dfs.blocksize"
參數來調整分片大小splitSize來調整最終分片個數,進而調整Mapper數量。
根據新版API中splitSize計算公式,一般情況下通過適當減小"mapreduce.input.fileinputformat.split.maxsize"
的值,並使其置於minSize與blockSize之間,則可以減小分片大小splitSize,來增加最終分片個數,進而增加Mapper數量。