2013-07-17 35 views
3

我試圖運行一個非常簡單的hadoop作業。它是對經典wordCount的修改,它不是對單詞進行計數,而是對文件中的行進行計數。我想用它來清理一堆我知道有重複的大日誌文件(每個大約70GB)。每一行都是一個「記錄」,因此我只想記錄一次記錄。Hadoop無法完成作業,因爲「設備上沒有剩餘空間」

我知道我的代碼是有效的,因爲它在我用小的普通文件運行時做了它應該做的事情。當我用大文件運行它時,Hadoop的行爲非常嚴格。首先,它在MAP階段正常開始工作,通常可以毫無問題地達到100%。然而,在處理REDUCE時,它永遠不會超過50%。它達到也許40%,然後再回到0%表現出一些異常「左設備上沒有空間」之後:

FSError: java.io.IOException: No space left on device 

,然後嘗試做再次減少和,當它達到40%,降至再次爲0%等等。當然,它會在它決定結束而沒有成功之前做2到3次。

雖然這個例外的問題是它不能與磁盤上的實際空間相關聯。磁盤空間永遠不會滿。不是HDFS上的全局(全局)空間,也不是每個節點中的單個磁盤。我檢查fs狀態:

$ hadoop dfsadmin -report > report 

此報告從不顯示實際節點達到100%。事實上,沒有一個節點接近那個。

我在每個節點中都有大約60GB的磁盤可用,而且我在一個有60個數據節點的集羣中運行它,這給我的總空間大於3TB。我正在處理的文件只有70GB。

從互聯網上看,我發現這可能與Hadoop在處理大量數據時創建太多文件有關。原始的wordCount代碼大大減少了數據(因爲單詞重複很多)。一個70GB的文件可以減少到只有7MB的輸出。但是,我期待的只是1/3減少,或者輸出大約20-30GB。

Unix類型的系統都帶有每個進程打開1024個文件的限制:

$ ulimit -n 
1024 

如果Hadoop是創造比這更多,這可能是一個問題。我要求系統管理員將該限制增加到65K,這就是現在的限制:

$ ulimit -n 
65000 

問題仍然存在。這可能是我需要進一步增加這個限制嗎?這裏還有其他事情嗎?

非常感謝您的幫助!

代碼在這裏:

package ...; 

import java.io.IOException; 
import java.util.StringTokenizer; 

import org.apache.hadoop.conf.Configuration; 
import org.apache.hadoop.fs.Path; 
import org.apache.hadoop.io.IntWritable; 
import org.apache.hadoop.io.Text; 
import org.apache.hadoop.mapreduce.Job; 
import org.apache.hadoop.mapreduce.Mapper; 
import org.apache.hadoop.mapreduce.Reducer; 
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; 
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; 
import org.apache.hadoop.util.GenericOptionsParser; 

public class LineCountMR { 

    public static class MapperClass 
     extends Mapper<Object, Text, Text, IntWritable>{ 

    private final static IntWritable one = new IntWritable(1); 
    private Text word = new Text(); 
    private String token = new String();   

    public void map(Object key, Text value, Context context 
        ) throws IOException, InterruptedException { 

     token = value.toString().replace(' ', '_'); 
     word.set(token); 
     context.write(word, one); 
    } 
    } 

    public static class ReducerClass 
     extends Reducer<Text,IntWritable,Text,IntWritable> { 
    private IntWritable result = new IntWritable(); 

    public void reduce(Text key, Iterable<IntWritable> values, 
         Context context 
         ) throws IOException, InterruptedException { 
     int sum = 0; 
     for (IntWritable val : values) { 
     sum += val.get(); 
     } 
     result.set(sum); 
     context.write(key, result); 
    } 
} 

    public static void main(String[] args) throws Exception { 
    Configuration conf = new Configuration();; 
    if (args.length != 2) { 
     System.err.println("Parameters: <in> <out>"); 
     System.exit(2); 
    } 
    Job job = new Job(conf, "line count MR"); 
    job.setJarByClass(LineCountMR.class); 
    job.setMapperClass(MapperClass.class); 
    job.setCombinerClass(ReducerClass.class); 
    job.setReducerClass(ReducerClass.class); 
    job.setOutputKeyClass(Text.class); 
    job.setOutputValueClass(IntWritable.class); 
    FileInputFormat.addInputPath(job, new Path(args[0])); 
    FileOutputFormat.setOutputPath(job, new Path(args[1])); 
    System.exit(job.waitForCompletion(true) ? 0 : 1); 
    } 
} 
+0

你正在運行多少個reducer,你配置了壓縮映射輸出,你使用了一個組合器嗎?你記錄了大量的調試信息嗎?你可以發佈代碼嗎? –

+0

通過任何機會,你可以看到你是否可以運行壓縮編解碼器來減少MR輸出的大小?這可以讓你確定這是否真的是空間問題。我遇到了一個問題,我正在對4.2GB的壓縮源文件運行我的工作,解壓縮爲120GB。由於MR輸出被解壓縮,它膨脹到230GB,因此我遇到了這個問題。你有什麼機會壓縮你的源文件? –

+0

感謝您的回覆。這裏回答你的問題: 對於Chris White: 「你運行多少個reducer,你配置了壓縮映射輸出嗎,你使用了一個組合器嗎?你記錄了大量的調試信息嗎?你能發佈代碼嗎? ?」 關於減速器,我使用的是標準配置。我沒有設置更多的減速器。我想這是每個節點2個映射器和2個reducer,對不對?我不使用組合器。我應該在這種情況下使用它嗎?關於調試消息,不。我沒有記錄他們(至少我沒有設置任何調試模式或任何東西)。 – ekorso

回答

4

在處理數據的10TB我見過的集羣上這個問題。此問題與HDFS上的空間可用性無關,而與本地文件系統(df -h)上的可用空間有關,用於存儲map-reduce操作期間生成的中間數據,該操作存儲在本地而非HDFS中。

0

對我來說,這是Hadoop的緩存目錄

[email protected]*-*-*-*:/tmp/hadoop-ubuntu/mapred/local/localRunner/ubuntu/jobcache 

清除它解決了這個問題。

相關問題