hadoop 分片与分块,map task和reduce task的理解
分塊:Block
HDFS存儲(chǔ)系統(tǒng)中,引入了文件系統(tǒng)的分塊概念(block),塊是存儲(chǔ)的最小單位,HDFS定義其大小為64MB。與單磁盤文件系統(tǒng)相似,存儲(chǔ)在 HDFS上的文件均存儲(chǔ)為多個(gè)塊,不同的是,如果某文件大小沒有到達(dá)64MB,該文件也不會(huì)占據(jù)整個(gè)塊空間。在分布式的HDFS集群上,Hadoop系統(tǒng)保證一個(gè)塊存儲(chǔ)在一個(gè)datanode上。
把File劃分成Block,這個(gè)是物理上真真實(shí)實(shí)的進(jìn)行了劃分,數(shù)據(jù)文件上傳到HDFS里的時(shí)候,需要?jiǎng)澐殖梢粔K一塊,每塊的大小由hadoop-default.xml里配置選項(xiàng)進(jìn)行劃分。一個(gè)大文件可以把劃分后的所有塊存儲(chǔ)到同一個(gè)磁盤上,也可以在每個(gè)磁盤上都存在這個(gè)文件的分塊。
這個(gè)就是默認(rèn)的每個(gè)塊64M:
<property> <name>dfs.block.size</name> <value>67108864</value> <description>The default block size for new files.</description> </property>數(shù)據(jù)劃分的時(shí)候有冗余,即進(jìn)行備份,個(gè)數(shù)是由以下配置指定的。具體的物理劃分步驟由Namenode決定。
1 <property> 2 <name>dfs.replication</name> 3 <value>3</value> 4 <description>Default block replication. 5 The actual number of replications can be specified when the file is created. 6 The default is used if replication is not specified in create time. 7 </description> 8 </property>分片:splits
由InputFormat這個(gè)接口來(lái)定義的,其中有個(gè)getSplits方法。這里有一個(gè)新的概念:fileSplit。每個(gè)map處理一個(gè)fileSplit,所以有多少個(gè)fileSplit就有多少個(gè)map(map數(shù)并不是單純的由用戶設(shè)置決定的)。
我們來(lái)看一下hadoop分配splits的源碼:
?
1 long goalSize = totalSize / (numSplits == 0 ? 1 : numSplits); 2 long minSize = Math.max(job.getLong("mapred.min.split.size", 1), minSplitSize); 3 4 for (FileStatus file: files) { 5 Path path = file.getPath(); 6 FileSystem fs = path.getFileSystem(job); 7 if ((length != 0) && isSplitable(fs, path)) { 8 long blockSize = file.getBlockSize(); 9 long splitSize = computeSplitSize(goalSize, minSize, blockSize); 10 11 long bytesRemaining = length; 12 while (((double) bytesRemaining)/splitSize > SPLIT_SLOP) { 13 String[] splitHosts = getSplitHosts(blkLocations,length-bytesRemaining, splitSize, clusterMap); 14 splits.add(new FileSplit(path, length-bytesRemaining, splitSize, splitHosts)); 15 bytesRemaining -= splitSize; 16 } 17 18 if (bytesRemaining != 0) { 19 splits.add(new FileSplit(path, length-bytesRemaining, bytesRemaining, blkLocations[blkLocations.length-1].getHosts())); 20 } 21 } else if (length != 0) { 22 String[] splitHosts = getSplitHosts(blkLocations,0,length,clusterMap); 23 splits.add(new FileSplit(path, 0, length, splitHosts)); 24 } else { 25 //Create empty hosts array for zero length files 26 splits.add(new FileSplit(path, 0, length, new String[0])); 27 } 28 } 29 30 return splits.toArray(new FileSplit[splits.size()]); 31 32 protected long computeSplitSize(long goalSize, long minSize, long blockSize) { 33 return Math.max(minSize, Math.min(goalSize, blockSize)); 34 }totalSize:是整個(gè)Map-Reduce job所有輸入的總大小。
numSplits:來(lái)自job.getNumMapTasks(),即在job啟動(dòng)時(shí)用org.apache.hadoop.mapred.JobConf.setNumMapTasks(int n)設(shè)置的值,給M-R框架的Map數(shù)量的提示。
goalSize:是輸入總大小與提示Map task數(shù)量的比值,即期望每個(gè)Mapper處理多少的數(shù)據(jù),僅僅是期望,具體處理的數(shù)據(jù)數(shù)由下面的computeSplitSize決定。
minSplitSize:默認(rèn)為1,可由子類復(fù)寫函數(shù)protected void setMinSplitSize(long minSplitSize) 重新設(shè)置。一般情況下,都為1,特殊情況除外。
minSize:取的1和mapred.min.split.size中較大的一個(gè)。
blockSize:HDFS的塊大小,默認(rèn)為64M,一般大的HDFS都設(shè)置成128M。
splitSize:就是最終每個(gè)Split的大小,那么Map的數(shù)量基本上就是totalSize/splitSize。
接下來(lái)看看computeSplitSize的邏輯:首先在goalSize(期望每個(gè)Mapper處理的數(shù)據(jù)量)和HDFS的block size中取較小的,然后與mapred.min.split.size相比取較大的。
?
一個(gè)片為一個(gè)splits,即一個(gè)map,只要搞清楚片的大小,就能計(jì)算出運(yùn)行時(shí)的map數(shù)。而一個(gè)split的大小是由goalSize, minSize, blockSize這三個(gè)值決定的。computeSplitSize的邏輯是,先從goalSize和blockSize兩個(gè)值中選出最小的那個(gè)(比如一般不設(shè)置map數(shù),這時(shí)blockSize為當(dāng)前文件的塊size,而goalSize是文件大小除以用戶設(shè)置的map數(shù)得到的,如果沒設(shè)置的話,默認(rèn)是1),在默認(rèn)的大多數(shù)情況下,blockSize比較小。然后再取blockSize和minSize中最大的那個(gè)。而minSize如果不通過(guò)”mapred.min.split.size”設(shè)置的話(”mapred.min.split.size”默認(rèn)為0),minSize為1,這樣得出的一個(gè)splits的size就是blockSize,即一個(gè)塊一個(gè)map,有多少塊就有多少map。
?
?
input_file_num : 輸入文件的個(gè)數(shù)(1)默認(rèn)map個(gè)數(shù)
如果不進(jìn)行任何設(shè)置,默認(rèn)的map個(gè)數(shù)是和blcok_size相關(guān)的。
default_num = total_size / block_size;
(2)期望大小
可以通過(guò)參數(shù)
mapred.map.tasks來(lái)設(shè)置程序員期望的map個(gè)數(shù),但是這個(gè)個(gè)數(shù)只有在大于default_num的時(shí)候,才會(huì)生效。
goal_num =mapred.map.tasks;
(3)設(shè)置處理的文件大小
可以通過(guò)mapred.min.split.size 設(shè)置每個(gè)task處理的文件大小,但是這個(gè)大小只有在大于
block_size的時(shí)候才會(huì)生效。
split_size = max(
mapred.min.split.size,
block_size);split_num = total_size / split_size;
(4)計(jì)算的map個(gè)數(shù)
compute_map_num = min(split_num, max(default_num, goal_num))
除了這些配置以外,mapreduce還要遵循一些原則。 mapreduce的每一個(gè)map處理的數(shù)據(jù)是不能跨越文件的,也就是說(shuō)max_map_num <= input_file_num。 所以,最終的map個(gè)數(shù)應(yīng)該為:
final_map_num = min(compute_map_num, input_file_num)
經(jīng)過(guò)以上的分析,在設(shè)置map個(gè)數(shù)的時(shí)候,可以簡(jiǎn)單的總結(jié)為以下幾點(diǎn):
(1)如果想增加map個(gè)數(shù),則設(shè)置mapred.map.tasks 為一個(gè)較大的值。
(2)如果想減小map個(gè)數(shù),則設(shè)置mapred.min.split.size 為一個(gè)較大的值。
map task
如何調(diào)整map數(shù)量:
有了2的分析,下面調(diào)整Map的數(shù)量就很容易了。
減小Map-Reduce job 啟動(dòng)時(shí)創(chuàng)建的Mapper數(shù)量
當(dāng)處理大批量的大數(shù)據(jù)時(shí),一種常見的情況是job啟動(dòng)的mapper數(shù)量太多而超出了系統(tǒng)限制,導(dǎo)致Hadoop拋出異常終止執(zhí)行。解決這種異常的思路是減少mapper的數(shù)量。具體如下:
輸入文件size巨大,但不是小文件
這種情況可以通過(guò)增大每個(gè)mapper的input size,即增大minSize或者增大blockSize來(lái)減少所需的mapper的數(shù)量。增大blockSize通常不可行,因?yàn)楫?dāng)HDFS被hadoop namenode -format之后,blockSize就已經(jīng)確定了(由格式化時(shí)dfs.block.size決定),如果要更改blockSize,需要重新格式化HDFS,這樣當(dāng)然會(huì)丟失已有的數(shù)據(jù)。所以通常情況下只能通過(guò)增大minSize,即增大mapred.min.split.size的值。
輸入文件數(shù)量巨大,且都是小文件
所謂小文件,就是單個(gè)文件的size小于blockSize。這種情況通過(guò)增大mapred.min.split.size不可行,需要使用FileInputFormat衍生的CombineFileInputFormat將多個(gè)input path合并成一個(gè)InputSplit送給mapper處理,從而減少mapper的數(shù)量。具體細(xì)節(jié)稍后會(huì)更新并展開。
增加Map-Reduce job 啟動(dòng)時(shí)創(chuàng)建的Mapper數(shù)量
增加mapper的數(shù)量,可以通過(guò)減小每個(gè)mapper的輸入做到,即減小blockSize或者減小mapred.min.split.size的值。
?
參考資料:
http://blog.csdn.net/strongerbit/article/details/7440111
http://blog.csdn.net/clerk0324/article/details/50887866
http://blog.csdn.net/yeruby/article/details/20068731
?http://zhidao.baidu.com/link?url=fLPxBdClbJ0R0-VGGiSbXR4bx9tlhadShKNYQ76CNrShD7Q7zsxr5b_df9gl7l5LA3VsXTkbeTvtOlj1fQY_yNx7bzopbfrW_tSbzN2J6Se
轉(zhuǎn)載于:https://www.cnblogs.com/qinwangchen/p/5837940.html
總結(jié)
以上是生活随笔為你收集整理的hadoop 分片与分块,map task和reduce task的理解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 关于llvm kaleidoscope:
- 下一篇: Androd安全——反编译技术完全解析