考究Hadoop中split的计算方法
Hadoop中block塊大小和split切片大小會(huì)影響到MapReduce程序在運(yùn)行過(guò)程中的效率、map的個(gè)數(shù)。在本文中,以經(jīng)典入門案例WordCount為例,通過(guò)debug的方式跟蹤源代碼,來(lái)分析hadoop中split的計(jì)算方法。
前期準(zhǔn)備
wc.txt的準(zhǔn)備?
單詞統(tǒng)計(jì),以空格為分割符對(duì)單詞進(jìn)行切割。因此wc.txt中的單詞都以空格進(jìn)行分割?
mr核心部分介紹?
map?
提取每一行,String[] arr = line.split(” “);
reduce?
對(duì)每一個(gè)key的個(gè)數(shù)進(jìn)行迭代,計(jì)算總數(shù)。
修改HDFS的文件塊大小
hdfs-default.xml?
首先查看默認(rèn)的配置信息?
文件塊的大小
最小文件塊的大小
<property><name>dfs.namenode.fs-limits.min-block-size</name><value>1048576</value><description>Minimum block size in bytes, enforced by the Namenode at createtime. This prevents the accidental creation of files with tiny blocksizes (and thus many blocks), which can degradeperformance.</description> </property>hdfs-site.xml?
了解默認(rèn)的配置信息之后,對(duì)其進(jìn)行修改
通過(guò)命令行查看屬性是否修改成功
$>hdfs getconf -confKey dfs.blocksize $>hdfs getconf -confKey dfs.namenode.fs-limits.min-block-size關(guān)鍵部分源碼解析
對(duì)所涉及到的關(guān)鍵部分,進(jìn)行解析?
org.apache.hadoop.mapreduce.JobSubmitter類
org.apache.hadoop.mapreduce.lib.input.FileInputFormat類
public List<InputSplit> getSplits(JobContext job) throws IOException {StopWatch sw = new StopWatch().start();// 通過(guò)getFormatMinSplitSize()方法 取得最小切片的大小為一個(gè)固定值(可通過(guò)配置文件配置得到)為0// 通過(guò)getMinSplitSize()方法 得到最小切片值為1// minSize的值為1long minSize = Math.max(getFormatMinSplitSize(), getMinSplitSize(job));// maxSize的值為:9223372036854775807long maxSize = getMaxSplitSize(job);// generate splits// 創(chuàng)建一個(gè)集合List<InputSplit> splits = new ArrayList<InputSplit>();// 得到hdfs的文件夾列表List<FileStatus> files = listStatus(job);// 得到每個(gè)文件的狀態(tài),進(jìn)行for循環(huán)for (FileStatus file: files) {// 取到文件的路徑Path path = file.getPath();// 取到文件的長(zhǎng)度long length = file.getLen();if (length != 0) {// 文件塊位置的數(shù)組BlockLocation[] blkLocations;if (file instanceof LocatedFileStatus) {// 通過(guò)getBlockLocations()方法得到文件塊的位置// blkLocations的值:[0,512,s103,s101,s104, 512,246,s103,s104,s102] 為兩塊文件塊blkLocations = ((LocatedFileStatus) file).getBlockLocations();} else {FileSystem fs = path.getFileSystem(job.getConfiguration());blkLocations = fs.getFileBlockLocations(file, 0, length);}// 判斷文本文件是否可切割if (isSplitable(job, path)) {// 得到塊大小// blockSize的值為512// 切片大小與塊大小、最小切片值、最大切片值有關(guān)long blockSize = file.getBlockSize();// 計(jì)算切片大小// blockSize=512;minSize=1;maxSize=9223372036854775807// splitSize的值為512long splitSize = computeSplitSize(blockSize, minSize, maxSize);...// 最終返回的值為一個(gè)切片集合// 具體的值為:[hdfs://s100/data/wc.txt:0+150, hdfs://s100/data/wc.txt:150+150, hdfs://s100/data/wc.txt:300+150, hdfs://s100/data/wc.txt:450+150, hdfs://s100/data/wc.txt:600+158]總共切了5個(gè)return splits;...// 得到切片大小的一個(gè)下限值,返回的是一個(gè)最小切片的字節(jié)數(shù)protected long getFormatMinSplitSize() {return 1;}...public static long getMinSplitSize(JobContext job) {// SPLIT_MINSIZE = mapreduce.input.fileinputformat.split.minsize(該配置項(xiàng)的默認(rèn)值為0)// job.getConfiguration().getLong(SPLIT_MINSIZE, 1L) = 0return job.getConfiguration().getLong(SPLIT_MINSIZE, 1L);}...public static long getMaxSplitSize(JobContext context) {// SPLIT_MAXSIZE = mapreduce.input.fileinputformat.split.maxsize// Long.MAX_VALUE的意思為取長(zhǎng)整型的最大值9223372036854775807// context.getConfiguration().getLong(SPLIT_MAXSIZE,Long.MAX_VALUE)的值為9223372036854775807return context.getConfiguration().getLong(SPLIT_MAXSIZE, Long.MAX_VALUE);}...protected long computeSplitSize(long blockSize, long minSize,long maxSize) {// 先在maxSize與blockSize之間選擇小的,再使用該值與minSize之間取得大的值// 就是取了三個(gè)值之間的中間值return Math.max(minSize, Math.min(maxSize, blockSize));}split計(jì)算方法
通過(guò)對(duì)源代碼的跟蹤,將split的計(jì)算方法總結(jié)如下:?
minSize = 1(默認(rèn)) (屬性名字:mapreduce.input.fileinputformat.split.minsize)?
maxSize = Long.MAX_VALUE(默認(rèn)) (屬性名字:mapreduce.input.fileinputformat.split.maxsize)?
blockSize = 512 (屬性名字:dfs.blocksize=128mb默認(rèn)值)?
計(jì)算方法:max(minSize,min(blockSize,maxSize))?
根據(jù)上述數(shù)據(jù),所以該過(guò)程中的切片大小為512
總結(jié)
以上是生活随笔為你收集整理的考究Hadoop中split的计算方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 聊聊CTR预估算法DeepFM
- 下一篇: MapReduce Job本地提交过程源