2016-07-13 11 views
1

Ich arbeite an einem MapReduce-Projekt mit Hadoop. Ich habe derzeit 3 ​​aufeinanderfolgende Jobs.Verwenden von Hadoop-Zählern - Mehrere Jobs

Ich möchte Hadoop-Zähler verwenden, aber das Problem ist, dass ich die tatsächliche Zählung im ersten Job machen möchte, aber auf den Zählerwert im Reducer des 3. Jobs zugreifen.

Wie kann ich das erreichen? Wo sollte ich die enum definieren? Muss ich es bestehen, warf den zweiten Job? Es wird auch helfen, ein Codebeispiel dafür zu sehen, da ich noch nichts finden konnte.

Hinweis: Ich bin mit Hadoop 2.7.2

EDIT: Ich habe bereits versucht, den Ansatz here erklärt und es gelang nicht. Mein Fall ist anders, da ich auf die Zähler von einem anderen Job zugreifen möchte. (nicht von Mapper zu Reducer).

Was ich versucht zu tun: First Job:

public static void startFirstJob(String inputPath, String outputPath) throws IOException, ClassNotFoundException, InterruptedException { 
    Configuration conf = new Configuration(); 
    Job job = Job.getInstance(conf, "wordCount"); 
    job.setJarByClass(WordCount.class); 
    job.setMapperClass(WordCountMapper.class); 
    job.setCombinerClass(WordCountReducer.class); 
    job.setReducerClass(WordCountReducer.class); 
    job.setOutputKeyClass(Text.class); 
    job.setOutputValueClass(LongWritable.class); 
    job.setInputFormatClass(SequenceFileInputFormat.class); 
    job.setOutputFormatClass(SequenceFileOutputFormat.class); 
    FileInputFormat.addInputPath(job, new Path(inputPath)); 
    FileOutputFormat.setOutputPath(job, new Path(outputPath)); 
    job.waitForCompletion(true); 
} 

Definierte der Zähler Enum in einer anderen Klasse:

public class CountersClass { 
    public static enum N_COUNTERS { 
     SOMECOUNT 
    } 
} 

Versuch Zähler zu lesen:

Cluster cluster = new Cluster(context.getConfiguration()); 
Job job = cluster.getJob(JobID.forName("wordCount")); 
Counters counters = job.getCounters(); 
CountersClass.N_COUNTERS mycounter = CountersClass.N_COUNTERS.valueOf("SOMECOUNT"); 
Counter c1 = counters.findCounter(mycounter); 
long N_Count = c1.getValue(); 
+0

Mögliches Duplikat [? Gibt es eine Möglichkeit Anzahl erfolgreicher Karten Aufgaben zuzugreifen aus einer Verringerung Aufgabe in einem MR-Job] (http://stackoverflow.com/questions/8009802/is-there-a-way-to-access-Nummer-of-Success-Map-Aufgaben-from-a-reduced-task-in-an) – tworec

+0

Ich denke, es ist keine gute Idee, Zähler von innen zu verwenden Job reduzieren. siehe http://stackoverflow.com/questions/8009802/is-there-a-way-to-access-number-of-successful-map-tasks-from-a-reduce-task-in-an/ – tworec

+0

Ja, Ich habe das schon gesehen und diesen Ansatz versucht. Aber in diesem Fall möchte er die Zähler innerhalb des Reduzierers (des gleichen Jobs) bekommen. Es ist nicht dasselbe wie in meinem Fall. –

Antwort

3

klassische Lösung ist Aufgabe des Zählerwert in eine Konfiguration eines nachfolgenden Jobs zu setzen, wo Sie es zugreifen müssen:

So stellen Sie sicher, dass es zu erhöhen, richtig in der Auszählung Job-Mapper/Reduktions:

context.getCounter(CountersClass.N_COUNTERS.SOMECOUNT).increment(1); 

Dann nach Auftragsabschluss zu zählen:

job.waitForCompletion(true); 

Counter someCount = job.getCounters().findCounter(CountersClass.N_COUNTERS.SOMECOUNT); 

//put counter value into conf object of the job where you need to access it 
//you can choose any name for the conf key really (i just used counter enum name here) 
job2.getConfiguration().setLong(CountersClass.N_COUNTERS.SOMECOUNT.name(), someCount.getValue()); 

Nächstes Stück ist es die in einer anderen Job-Mapper/Minderer zuzugreifen. Gerade außer Kraft setzt setup() Zum Beispiel:

private long someCount; 

@Override 
protected void setup(Context context) throws IOException, 
    InterruptedException { 
    super.setup(context); 
    this.someCount = context.getConfiguration().getLong(CountersClass.N_COUNTERS.SOMECOUNT.name(), 0)); 
} 
+0

Danke! Was, wenn ich mehr als einen Zähler in diesem 'enum' habe? kann ich 'setLong' und' getLong' durch 'setEnum' und' getEnum' ersetzen? Oder muss ich es tun, was Sie für alle Zähler gesagt haben? –

+1

Jedes Enum-Element sollte einem separaten Config-Schlüssel entsprechen. Sie verwenden setLong getLong immer noch, um auf sie mit ihren jeweiligen Schlüsseln zuzugreifen. – yurgis

+0

Ich weiß, das ist eine alte Frage. Nehmen wir jedoch an, dass die Jobs nach einer gewissen Verzögerung starten. Überschreibt der verzögerte Job nicht den Zähler, der vom zuvor gestarteten Job gesetzt wurde, wenn er auf einem Cluster ausgeführt wird? – user238607

2

Get die Zähler am Ende Ihres ersten Jobs und schreiben Sie ihren Wert in eine Datei und lesen Sie es in Ihnen sub-se Quent Job. Schreiben Sie es in HDFS, wenn Sie es vom Reducer oder in der lokalen Datei lesen möchten, wenn Sie den Anwendungscode lesen und initialisieren.

Counters counters = job.getCounters(); Counter c1 = counters.findCounter(COUNTER_NAME); System.out.println(c1.getDisplayName()+":"+c1.getValue());

Lesen und Schreiben von Dateien Teil der grundlegenden Tutorials ist.

+0

Das könnte eine Option sein. Können Sie bitte den dafür benötigten Codeabschnitt hinzufügen? danke –