2011-10-06 174 views
4

我試着去學習潛水HDFS中存儲的文件到分裂和讀給不同的過程(在不同的機器。)的Hadoop在同樣大小分割文件

我想到的是,如果我有一個包含1200條記錄與SequenceFile 12過程中,我會看到每個過程大約有100條記錄。劃分文件的方式是獲取數據長度,然後除以進程數,爲每個分割導出chunk/beg/end大小,然後將該分割通過例如SequenceFileRecordReader,在簡單的while循環中檢索記錄:代碼如下。

private InputSplit getSplit(int id) throws IOException { 
... 
    for(FileStatus file: status) { 
     long len = file.getLen(); 
     BlockLocation[] locations = 
      fs.getFileBlockLocations(file, 0, len); 
     if (0 < len) { 
      long chunk = len/n; 
      long beg = (id*chunk)+(long)1; 
      long end = (id)*chunk; 
      if(n == (id+1)) end = len; 
      return new FileSplit(file, beg, end, locations[locations.length-1].getHosts()); 
     } 
    } 
... 
} 

但是,結果顯示每個進程統計的總記錄總數與存儲在文件中的記錄不同。將SequenceFile均勻分成塊並將它們分發到不同主機的正確方法是什麼?

謝謝。

回答

4

我不禁想知道你爲什麼試圖做這樣的事情。 Hadoop自動將您的文件和1200條記錄拆分爲100條記錄,聽起來不像很多數據。如果你詳細說明你的問題,有人可能會更直接地幫助你。

這裏是我的兩個想法:


選項1:使用Hadoop的自動拆分行爲

的Hadoop將自動把您的文件。文件分割成的塊的數量是文件的總大小除以塊大小。默認情況下,一個地圖任務將被分配給每個塊(不是每個文件)。

在您的conf/hdfs-site.xml配置文件中,有一個dfs.block.size參數。大多數人將其設置爲64或128mb。然而,如果你想要做一些小事情,比如每個塊有100個序列文件記錄,你可以把它設置得非常低......說1000個字節。我從來沒有聽說過任何人想要這樣做,但它是一種選擇。


選項2:使用MapReduce作業來拆分數據。

有你的工作使用「身份映射器」(基本上實現映射器,不要覆蓋map)。此外,你的工作使用「身份縮減器」(基本上實施減速器,不要覆蓋reduce)。將縮減器的數量設置爲您想要的分割數。假設你有三個序列文件要分成25個文件,你需要加載這3個文件,並將reducer的數量設置爲25.記錄將隨機發送給每個reducer,最終結果會接近25次平分。

這是有效的,因爲身份映射器和reducer實際上不會做任何事情,所以您的記錄將保持不變。記錄被髮送到隨機減速器,然後它們將被寫出,每個減速器一個文件到part-r-xxxx文件中。這些文件中的每一個都將包含你的序列文件,甚至可以將它們分成幾塊。

相關問題