복붙노트

[HADOOP] Hadoop Map Reduce에서 파트 파일 이름 바꾸기

HADOOP

Hadoop Map Reduce에서 파트 파일 이름 바꾸기

http://hadoop.apache.org/docs/mapreduce/r0.21.0/api/index.html?org/apache/hadoop/mapreduce/lib/output/ 페이지의 예제에 따라 MultipleOutputs 클래스를 사용하려고했습니다. MultipleOutputs.html

드라이버 코드

    Configuration conf = new Configuration();
    Job job = new Job(conf, "Wordcount");
    job.setJarByClass(WordCount.class);
    job.setInputFormatClass(TextInputFormat.class);
    job.setMapperClass(WordCountMapper.class);
    job.setReducerClass(WordCountReducer.class);
    job.setMapOutputKeyClass(Text.class);
    job.setMapOutputValueClass(IntWritable.class);
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);
    FileInputFormat.setInputPaths(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));
    MultipleOutputs.addNamedOutput(job, "text", TextOutputFormat.class,
            Text.class, IntWritable.class);
    System.exit(job.waitForCompletion(true) ? 0 : 1);

감속기 코드

public class WordCountReducer extends
        Reducer<Text, IntWritable, Text, IntWritable> {
    private IntWritable result = new IntWritable();
    private MultipleOutputs<Text, IntWritable> mos;
    public void setup(Context context){
        mos = new MultipleOutputs<Text, IntWritable>(context);
    }
    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);
        mos.write("text", key,result);
    }
    public void cleanup(Context context)  {
         try {
            mos.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
         }
}

감속기의 출력이 text-r-00000으로 이름이 변경된 것으로 확인되었습니다.

하지만 여기서 문제는 비어있는 part-r-00000 파일도 얻게된다는 것입니다. MultipleOutputs가 어떻게 동작 할 것인가, 아니면 내 코드에 문제가 있습니까? 제발 조언.

필자가 시도한 또 다른 대안은 FileSystem 클래스를 사용하여 출력 폴더를 반복하고 부분으로 시작하는 모든 파일의 이름을 수동으로 바꾸는 것입니다.

가장 좋은 방법은 무엇입니까?

FileSystem hdfs = FileSystem.get(configuration);
FileStatus fs[] = hdfs.listStatus(new Path(outputPath));
for (FileStatus aFile : fs) {
if (aFile.isDir()) {
hdfs.delete(aFile.getPath(), true);
// delete all directories and sub-directories (if any) in the output directory
} 
else {
if (aFile.getPath().getName().contains("_"))
hdfs.delete(aFile.getPath(), true);
// delete all log files and the _SUCCESS file in the output directory
else {
hdfs.rename(aFile.getPath(), new Path(myCustomName));
}
}

해결법

  1. ==============================

    1.MultipleOutputs를 사용하는 경우에도 기본 OutputFormat (TextOutputFormat이라고 생각합니다)이 여전히 사용되고 있으므로 사용자가보고있는 part-r-xxxxx 파일을 초기화하고 작성합니다.

    MultipleOutputs를 사용하는 경우에도 기본 OutputFormat (TextOutputFormat이라고 생각합니다)이 여전히 사용되고 있으므로 사용자가보고있는 part-r-xxxxx 파일을 초기화하고 작성합니다.

    당신이 MultipleOutputs를 사용하기 때문에 어떤 context.write도하지 않기 때문에 그들이 비어 있다는 사실입니다. 하지만 초기화 중에 생성되지는 않습니다.

    그것들을 없애기 위해서는 OutputFormat을 정의하여 출력을 기대하지 말아야한다. 다음과 같이 할 수 있습니다.

    job.setOutputFormat(NullOutputFormat.class);
    

    이 프로퍼티 세트를 사용하면 파트 파일이 전혀 초기화되지 않도록 보장해야하지만 Multiple Outputs에서 여전히 출력을 얻을 수 있습니다.

    아마도 LazyOutputFormat을 사용하여 데이터가 있거나 빈 파일을 초기화하지 않을 때만 출력 파일을 만들 수 있습니다. 당신은 이렇게 할 수 있습니다.

    import org.apache.hadoop.mapreduce.lib.output.LazyOutputFormat; 
    LazyOutputFormat.setOutputFormatClass(job, TextOutputFormat.class);
    

    Reducer에서 namedOutput에 기반하여 생성 될 기본 출력 경로를 사용하는 Multiple Output.write (String namedOutput, K key, V value) 프로토 타입을 {namedOutput} - (m | r) - (부분 번호). 출력 파일 이름을보다 잘 제어하고 싶다면 키 / 값에 따라 런타임에 생성 된 파일 이름을 얻을 수있는 MultipleOutputs.write (String namedOutput, K key, V value, String baseOutputPath) 프로토 타입을 사용해야합니다.

  2. ==============================

    2.다음은 출력 파일의 기본 이름을 변경하기 위해 Driver 클래스에서 수행해야하는 작업입니다.     job.getConfiguration (). set ( "mapreduce.output.basename", "text"); 그러면 파일 이름이 "text-r-00000"이됩니다.

    다음은 출력 파일의 기본 이름을 변경하기 위해 Driver 클래스에서 수행해야하는 작업입니다.     job.getConfiguration (). set ( "mapreduce.output.basename", "text"); 그러면 파일 이름이 "text-r-00000"이됩니다.

  3. from https://stackoverflow.com/questions/14555313/renaming-part-files-in-hadoop-map-reduce by cc-by-sa and MIT license