2016-07-13 88 views
1

我正在使用Hadoop進行mapreduce項目。我目前有3個連續工作。使用Hadoop計數器 - 多個作業

我想使用Hadoop計數器,但問題是我想在第一個作業中進行實際計數,但訪問第三個作業的減速器中的計數器值。

我該如何做到這一點?我應該在哪裏定義enum?我需要通過它扔第二份工作嗎?這也將有助於看到一些代碼示例,因爲我還找不到任何東西。

注:我使用Hadoop 2.7.2

編輯:我已經想盡了辦法解釋here,並沒有成功。我的情況是不同的,因爲我想訪問來自不同工作的計數器。 (不是從映射器到還原器)。

我試圖這樣做: 第一份工作:

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); 
} 

定義在不同的類中的計數器枚舉:

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

試圖讀取計數器:

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

的[?有沒有一種方法來訪問從降低任務的MR工作的成功map任務數(可能的複製http://stackoverflow.com/questions/8009802/is-there-a-way-to-access-number-of-successful-map-tasks-from-a-reduce-task-in-an) – tworec

+0

我認爲從內部使用計數器並不是一個好主意減少工作。請參閱http://stackoverflow.com/questions/8009802/is-there-a-way-to-access-number-of-successful-map-tasks-from-a-reduce-task-in-an/ – tworec

+0

是的,我已經看到了這一點,我嘗試了這種方法。但是在那種情況下,他想讓減速器內部的計數器(同一工作)。這與我的情況不一樣。 –

回答

3

經典的解決辦法是把工作的計數器值在你需要訪問它的後續作業的配置:

因此,請務必在點票工作映射器/減速器正確地增加它:

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

然後計算工作完成後:

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()); 

下一塊是訪問它在另一個作業的映射器/減速。只是重寫設置() 例如:

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

謝謝!如果我在這個'enum'裏有更多的計數器呢?我可以用'setEnum'和'getEnum'來代替'setLong'和'getLong'嗎?或者我需要爲所有櫃檯所說的做什麼? –

+1

每個枚舉項目應該對應一個單獨的配置項。你仍然使用setLong getLong來通過它們各自的鍵訪問它們 – yurgis

+0

我知道這是個老問題。但是讓我們假設作業在某個延遲之後開始,在集羣上運行時,延遲的作業不會覆蓋早期啓動的作業設置的計數器嗎? – user238607

2

獲取第一份工作結束時的計數器,並將它們的值寫入文件並在其中進行閱讀奇怪的工作。如果你想從reducer或本地文件讀取它,如果你將讀取和初始化應用程序代碼,將它寫入HDFS。

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

讀取和寫入文件的基本教程的一部分。

+0

這可能是一個選項。你能否添加這部分所需的代碼?謝謝 –