Hadoop框架下MapReduce中的map個數如何控制

林六天發表於2015-01-22

控制map個數的核心原始碼

 1 long minSize = Math.max(getFormatMinSplitSize(), getMinSplitSize(job));
 2  
 3 //getFormatMinSplitSize 預設返回1,getMinSplitSize 為使用者設定的最小分片數, 如果使用者設定的大於1,則為使用者設定的最小分片數
 4 long maxSize = getMaxSplitSize(job);
 5  
 6 //getMaxSplitSize為使用者設定的最大分片數,預設最大為long 9223372036854775807L
 7  
 8 long splitSize = computeSplitSize(blockSize, minSize,
 9                             maxSize);
10  
11 protected long computeSplitSize(long blockSize, long minSize, long maxSize) {
12         return Math.max(minSize, Math.min(maxSize, blockSize));
13     }

由上述程式碼可以看出在

maxSize預設等於long(長整形)

blockSize預設在hadoop2.0之後為128M

minSize預設等於1

因此預設的切片大小splitSize等於128M也就是說等於塊大小

一個切片對應於一個map任務,因此在預設情況下一個塊對應於一個map任務。

要想人為控制map的個數可以從minSize和MaxSize入手。

想要增加map的個數,可以將maxSize調整小於blockSize;想要減小map的個數,可以調整minSize>blockSize。

具體調整可以在job配置中增加如下配置

   FileInputFormat.setMinInputSplitSize(job, 301349250);//設定minSize
   FileInputFormat.setMaxInputSplitSize(job, 10000);//設定maxSize

在實驗中,

測試 檔案大小 297M(311349250)

塊大小128M

測試程式碼

   FileInputFormat.setMinInputSplitSize(job, 301349250);   

  FileInputFormat.setMaxInputSplitSize(job, 10000);

測試後Map個數為1,由上面分片公式算出分片大小為301349250, 比 311349250小, 理論應該為兩個map,  這是為什麼呢?在上原始碼

while (bytesRemaining / splitSize > 1.1D) {
                        int blkIndex = getBlockIndex(blkLocations, length
                                - bytesRemaining);
                        splits.add(makeSplit(path, length - bytesRemaining,
                                splitSize, blkLocations[blkIndex].getHosts()));

                        bytesRemaining -= splitSize;
                    }

可以看出只要剩餘的檔案大小不超過分片大小的1.1倍, 則會分到一個分片中,避免開兩個MAP, 其中一個執行資料太小,浪費資源。

總結,分片過程大概為,先遍歷目標檔案,過濾部分不符合要求的檔案, 然後新增到列表,然後按照檔名來切分分片 (大小為前面計算分片大小的公式, 最後有個檔案尾可能合併,其實常寫網路程式的都知道), 然後新增到分片列表,然後每個分片讀取自身對應的部分給MAP處理

 

相關文章