복붙노트

[HADOOP] Hadoop 작업의 기존 출력 경로를 다시 덮어 쓰거나 재사용하는 방법

HADOOP

Hadoop 작업의 기존 출력 경로를 다시 덮어 쓰거나 재사용하는 방법

나는 매일 Hadoop 작업을 실행할 때 기존 출력 디렉토리를 덮어 쓰거나 재사용하고 싶다. 실제로 출력 디렉토리에는 매일 실행 된 작업 결과의 요약 출력이 저장됩니다. 동일한 출력 디렉토리를 지정하면 "output directory already exists"오류가 발생합니다.

이 유효성 검사를 무시하는 방법?

해결법

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

    1.작업을 실행하기 전에 디렉토리를 삭제하는 것은 어떻습니까?

    작업을 실행하기 전에 디렉토리를 삭제하는 것은 어떻습니까?

    쉘을 통해이 작업을 수행 할 수 있습니다.

    hadoop fs -rmr /path/to/your/output/
    

    또는 자바 API를 통해 :

    // configuration should contain reference to your namenode
    FileSystem fs = FileSystem.get(new Configuration());
    // true stands for recursively deleting the folder you gave
    fs.delete(new Path("/path/to/your/output"), true);
    
  2. ==============================

    2.Jungblut의 대답은 당신의 직접적인 해결책입니다. 자동화 된 프로세스 (개인적으로)를 삭제하는 자동화 된 프로세스를 절대로 믿지 않으므로 대안을 제안 할 것입니다.

    Jungblut의 대답은 당신의 직접적인 해결책입니다. 자동화 된 프로세스 (개인적으로)를 삭제하는 자동화 된 프로세스를 절대로 믿지 않으므로 대안을 제안 할 것입니다.

    덮어 쓰기를 시도하는 대신 작업이 실행 된 시간을 포함하여 작업의 출력 이름을 동적으로 만들 것을 제안합니다.

    "/ path / to / your / output-2011-10-09-23-04 /"와 같은 것입니다. 이렇게하면 다시 방문해야 할 경우에 대비하여 이전 작업 산출물을 계속 유지할 수 있습니다. 일일 10 개 이상의 작업을 실행하는 시스템에서 출력은 / output / job1 / 2011 / 10 / 09 / job1out / part-r-xxxxx, / output / job1 / 2011 / 10 / 10 / job1out / part-r-xxxxx 등이 있습니다.

  3. ==============================

    3.Hadoop의 TextInputFormat (사용하고있는 것으로 추측)은 기존 디렉토리를 덮어 쓸 수 없습니다. 아마도 당신이 실수로 당신과 당신의 집단이 열심히 일하는 것을 삭제했다는 사실을 깨닫게 될지도 모른다.

    Hadoop의 TextInputFormat (사용하고있는 것으로 추측)은 기존 디렉토리를 덮어 쓸 수 없습니다. 아마도 당신이 실수로 당신과 당신의 집단이 열심히 일하는 것을 삭제했다는 사실을 깨닫게 될지도 모른다.

    그러나 작업에 의해 출력 폴더를 덮어 쓰는 것이 확실한 경우 가장 간단한 방법은 TextOutputFormat을 다음과 같이 약간 변경하는 것입니다.

    public class OverwriteTextOutputFormat<K, V> extends TextOutputFormat<K, V>
    {
          public RecordWriter<K, V> 
          getRecordWriter(TaskAttemptContext job) throws IOException, InterruptedException 
          {
              Configuration conf = job.getConfiguration();
              boolean isCompressed = getCompressOutput(job);
              String keyValueSeparator= conf.get("mapred.textoutputformat.separator","\t");
              CompressionCodec codec = null;
              String extension = "";
              if (isCompressed) 
              {
                  Class<? extends CompressionCodec> codecClass = 
                          getOutputCompressorClass(job, GzipCodec.class);
                  codec = (CompressionCodec) ReflectionUtils.newInstance(codecClass, conf);
                  extension = codec.getDefaultExtension();
              }
              Path file = getDefaultWorkFile(job, extension);
              FileSystem fs = file.getFileSystem(conf);
              FSDataOutputStream fileOut = fs.create(file, true);
              if (!isCompressed) 
              {
                  return new LineRecordWriter<K, V>(fileOut, keyValueSeparator);
              } 
              else 
              {
                  return new LineRecordWriter<K, V>(new DataOutputStream(codec.createOutputStream(fileOut)),keyValueSeparator);
              }
          }
    }
    

    이제 overwrite = true를 사용하여 FSDataOutputStream (fs.create (file, true))을 만듭니다.

  4. ==============================

    4.Hadoop은 이미 작업에 대한 여러 입력 경로를 허용하여 달성하려는 것으로 보이는 효과를 지원합니다. 파일을 더 추가 할 단일 파일 디렉토리를 가지려는 대신 새 디렉토리를 추가 할 디렉토리 디렉토리를 지정하십시오. 집계 결과를 입력으로 사용하려면 입력 glob를 하위 디렉토리 (예 : my-aggregate-output / *)에 대해 와일드 카드로 지정하면됩니다. 새 데이터를 집계에 출력으로 추가하려면 일반적으로 집계의 새로운 고유 하위 디렉토리를 출력 디렉토리로 지정하십시오. 일반적으로 타임 스탬프 또는 입력 데이터에서 파생 된 시퀀스 번호 (예 : my-aggregate-output / 20140415154424)를 사용하십시오.

    Hadoop은 이미 작업에 대한 여러 입력 경로를 허용하여 달성하려는 것으로 보이는 효과를 지원합니다. 파일을 더 추가 할 단일 파일 디렉토리를 가지려는 대신 새 디렉토리를 추가 할 디렉토리 디렉토리를 지정하십시오. 집계 결과를 입력으로 사용하려면 입력 glob를 하위 디렉토리 (예 : my-aggregate-output / *)에 대해 와일드 카드로 지정하면됩니다. 새 데이터를 집계에 출력으로 추가하려면 일반적으로 집계의 새로운 고유 하위 디렉토리를 출력 디렉토리로 지정하십시오. 일반적으로 타임 스탬프 또는 입력 데이터에서 파생 된 시퀀스 번호 (예 : my-aggregate-output / 20140415154424)를 사용하십시오.

  5. ==============================

    5.각 실행마다 시간별 출력 하위 디렉토리를 만들 수 있습니다. 예를 들어 사용자가 출력 디렉토리를 예상하고 다음과 같이 설정한다고 가정 해 보겠습니다.

    각 실행마다 시간별 출력 하위 디렉토리를 만들 수 있습니다. 예를 들어 사용자가 출력 디렉토리를 예상하고 다음과 같이 설정한다고 가정 해 보겠습니다.

    FileOutputFormat.setOutputPath(job, new Path(args[1]);
    

    이것을 다음 행으로 변경하십시오.

    String timeStamp = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss", Locale.US).format(new Timestamp(System.currentTimeMillis()));
    FileOutputFormat.setOutputPath(job, new Path(args[1] + "/" + timeStamp));
    
  6. ==============================

    6.비슷한 사용 사례가 있었는데, 이것을 해결하기 위해 MultipleOutputs를 사용합니다.

    비슷한 사용 사례가 있었는데, 이것을 해결하기 위해 MultipleOutputs를 사용합니다.

    예를 들어, 다른 MapReduce 작업이 같은 디렉토리 / outputDir /에 쓰길 원한다면. 작업 1은 /outputDir/job1-part1.txt에 기록하고 작업 2는 /outputDir/job1-part2.txt에 기록합니다 (기존 파일을 삭제하지 않음).

    주 디렉토리에서 출력 디렉토리를 임의로 설정하십시오 (새 작업이 실행되기 전에 삭제 될 수 있음).

    FileInputFormat.addInputPath(job, new Path("/randomPath"));
    

    축소 기 / 매퍼에서 MultipleOutputs를 사용하고 작성기가 원하는 디렉토리에 쓰도록 설정하십시오.

    public void setup(Context context) {
        MultipleOutputs mos = new MultipleOutputs(context);
    }
    

    과:

    mos.write(key, value, "/outputDir/fileOfJobX.txt")
    

    그러나 사용 사례는 그보다 조금 복잡했습니다. 동일한 플랫 디렉토리에 작성하는 경우 다른 디렉토리에 쓰고 스크립트를 실행하여 다음과 같이 파일을 마이그레이션 할 수 있습니다. hadoop fs -mv / tmp / * / outputDir

    필자의 경우, 각 MapReduce 작업은 작성중인 메시지의 값을 기반으로 다른 하위 디렉토리에 씁니다. 디렉토리 구조는 다음과 같이 다중 계층이 될 수 있습니다.

    /outputDir/
        messageTypeA/
            messageSubTypeA1/
                job1Output/
                    job1-part1.txt
                    job1-part2.txt
                    ...
                job2Output/
                    job2-part1.txt
                    ...
    
            messageSubTypeA2/
            ...
        messageTypeB/
        ...
    

    각 Mapreduce 작업은 수천 개의 하위 디렉토리에 쓸 수 있습니다. 그리고 tmp 디렉토리에 쓰고 각 파일을 올바른 디렉토리로 옮기는 데 드는 비용은 높습니다.

  7. ==============================

    7.로컬 파일 시스템에서 입력 파일 (예 : 첨부 된 항목 포함)을 hadoop 분산 파일 시스템으로로드하는 경우 :

    로컬 파일 시스템에서 입력 파일 (예 : 첨부 된 항목 포함)을 hadoop 분산 파일 시스템으로로드하는 경우 :

    hdfs dfs -put  /mylocalfile /user/cloudera/purchase
    

    그런 다음 기존 출력 디렉토리를 -f로 덮어 쓰거나 재사용 할 수도 있습니다. 폴더를 삭제하거나 다시 만들 필요가 없습니다.

    hdfs dfs -put -f  /updated_mylocalfile /user/cloudera/purchase
    
  8. ==============================

    8.Hadoop은 Write Once, Read Many times라는 철학을 따릅니다. 따라서 디렉토리에 다시 쓰기를 시도 할 때 새로운 디렉토리 (Write Once)가 있지만 이미 존재한다고 가정하므로 불평합니다. hadoop fs -rmr / path / to / your / output /을 통해 삭제할 수 있습니다. 데이터를 보존하려면 동적 디렉토리 (예 : 타임 스탬프 또는 해시 값을 기반으로)를 만드는 것이 좋습니다.

    Hadoop은 Write Once, Read Many times라는 철학을 따릅니다. 따라서 디렉토리에 다시 쓰기를 시도 할 때 새로운 디렉토리 (Write Once)가 있지만 이미 존재한다고 가정하므로 불평합니다. hadoop fs -rmr / path / to / your / output /을 통해 삭제할 수 있습니다. 데이터를 보존하려면 동적 디렉토리 (예 : 타임 스탬프 또는 해시 값을 기반으로)를 만드는 것이 좋습니다.

  9. from https://stackoverflow.com/questions/7713316/how-to-overwrite-reuse-the-existing-output-path-for-hadoop-jobs-again-and-agian by cc-by-sa and MIT license