天天看點

[Hadoop源碼解讀](四)MapReduce篇之Counter相關類

[Hadoop源碼解讀](四)MapReduce篇之Counter相關類

  當我們定義一個Counter時,我們首先要定義一枚舉類型:

public static enum MY_COUNTER{  
  CORRUPTED_DATA_COUNTER,  
  NORMAL_DATA_COUNTER  
};      

 然後,我們就可以在mapper或reducer裡面增加它的值:

context.getCounter(MY_COUNTER.CORRUPTED_DATA_COUNTER).increment(1);      

我們在第(一)篇講InputFormat時,我們有看到Mapper.class中的Context類是繼承與MapContext類的,而MapContext又繼承與TaskInputOutputContext,我們可以從TaskInputOutputContext的getCounter()方法看見,這個方法實際上是調用了StatusReporter的getCounter()方法,StatusReporter在後面談到。

  接着,我們在送出job,waitForCompletion()方法等待job執行完後,就可以通過

Counters counters = job.getCounters();  
Counter counter = counters.findCounter(MYCOUNTER.CORRUPTED_DATA_COUNTER);  
System.out.println(counter.getValue());      

這樣就将我們想要輸出的計數器輸出來。

  Counter對應我們寫的enum類型中的一個枚舉常量,比如MY_COUNTER.CORRUTED_DATA_COUNTER,它由name,displayName和value表示,value是Counter目前計數值。Counter、CounterGroup和Counters都實作了Writable接口,由于Counter是全局的,是以它們的讀寫方法都是synchronized方法,以保證線程安全。

  CounterGroup對應我們寫的enum類型,比如MY_COUNTER。CounterGroup有name,displayName,TreeMap類型的counters,以及一個ResourceBoundle bundle。counters存放的是enum裡面的所有枚舉常量對應的Counter。而bundle是用來本地化Counter的名字的。舉個例子:src\mapred\org\apache\hadoop\mapred下有一個JobInProgress_Counter.properties檔案,内容是這樣的:

# ResourceBundle properties file for job-level counters  
  
CounterGroupName=                  Job Counters   
  
NUM_FAILED_MAPS.name=              Failed map tasks  
NUM_FAILED_REDUCES.name=           Failed reduce tasks  
TOTAL_LAUNCHED_MAPS.name=          Launched map tasks  
TOTAL_LAUNCHED_REDUCES.name=       Launched reduce tasks  
OTHER_LOCAL_MAPS.name=             Other local map tasks  
DATA_LOCAL_MAPS.name=              Data-local map tasks  
RACK_LOCAL_MAPS.name=              Rack-local map tasks  
FALLOW_SLOTS_MILLIS_MAPS.name=     Total time spent by all maps waiting after reserving slots (ms)  
FALLOW_SLOTS_MILLIS_REDUCES.name=  Total time spent by all reduces waiting after reserving slots (ms)      

它存放的是job級别的counters的本地化名字。形式是name = displayName。

這樣,我們就可以每次利用name從改檔案中讀取displayName,使得當我們改變這個properties檔案中的某個displayName的時候,不需要改動程式。

繼續閱讀