【MapReduce】Mapreduce基礎知識整理 (六) 全局計算器

1. 什麼是全局計數器

計數器是用來記錄job的執行進度和狀態的。它的作用可以理解爲日誌。我們可以在程序的某個位置插入計數器,記錄數據或者進度的變化情況。

MapReduce 計數器(Counter)爲我們提供一個窗口,用於觀察 MapReduce Job 運行期的各種細節數據。對MapReduce性能調優很有幫助,MapReduce性能優化的評估大部分都是基於這些 Counter 的數值表現出來的。

例如wordcount過程中,統計輸入數據條數:
4個小文件,4個maptask
wc0.txt——maptask0——27
wc1.txt——maptask1——27
wc2.txt——maptask2——27
wc3.txt——maptask3——27
輸入數據條數=4個maptask輸入條數之和 27*4=108

觀察下邊輸出 Map input records=108

mpareduce中的默認的計數器統計的參數:
每一個mapreduce的job執行完成都會有一個計數器統計的報文:
	File System Counters   文件系統的計數器  文件系統的讀寫字節
		FILE: Number of bytes read=6761
		FILE: Number of bytes written=1510365
		FILE: Number of read operations=0
		FILE: Number of large read operations=0
		FILE: Number of write operations=0
		HDFS: Number of bytes read=8736
		HDFS: Number of bytes written=75
		HDFS: Number of read operations=46
		HDFS: Number of large read operations=0
		HDFS: Number of write operations=7
	Map-Reduce Framework  mapreduce計算框架的計數器
		Map input records=108   map的輸入的數據條數
		Map output records=552  map輸出的數據條數  context.write()調用的次數  單詞的個數552
		Map output bytes=4704  map的輸出的字節
		Map output materialized bytes=440   map輸出的元數據字節
		Input split bytes=360  輸入切片的大小
		
		
		Combine input records=552   combine輸入的數據條數=map輸出
		Combine output records=40   combine輸出的數據條數=reduce的輸入
		
		
		Reduce input groups=10   reduce的輸入的數據組
		Reduce shuffle bytes=440  
		Reduce input records=40
		Reduce output records=10  reduce的輸出的數據條數
		
		
		Spilled Records=80  溢寫的數據條數  40原始數據  40元數據
		Shuffled Maps =4
		Failed Shuffles=0
		Merged Map outputs=4
		GC time elapsed (ms)=10
		Total committed heap usage (bytes)=2426929152
	Shuffle Errors  shuffle錯誤的計數器
		BAD_ID=0
		CONNECTION=0
		IO_ERROR=0  IO是否有錯誤
		WRONG_LENGTH=0
		WRONG_MAP=0
		WRONG_REDUCE=0
	File Input Format Counters 
		Bytes Read=2496
	File Output Format Counters 
		Bytes Written=75
		

2. 常用全局計數器

MapReduce 自帶了許多默認Counter,現在我們來分析這些默認 Counter 的含義,方便大家觀察 Job 結果,如輸入的字節數、輸出的字節數、Map端輸入/輸出的字節數和條數、Reduce端的輸入/輸出的字節數和條數等。下面我們只需瞭解這些內置計數器,知道計數器組名稱(groupName)和計數器名稱(counterName),以後使用計數器會查找groupName和counterName即可。

2.1 任務計數器

在任務執行過程中,任務計數器採集任務的相關信息,每個作業的所有任務的結果會被聚集起來。例如,MAP_INPUT_RECORDS 計數器統計每個map任務輸入記錄的總數,並在一個作業的所有map任務上進行聚集,使得最終數字是整個作業的所有輸入記錄的總數。任務計數器由其關聯任務維護,並定期發送給TaskTracker,再由TaskTracker發送給 JobTracker。因此,計數器能夠被全局地聚集。下面我們分別瞭解各種任務計數器。

2.1.1 MapReduce 任務計數器

MapReduce 任務計數器的 groupName爲org.apache.hadoop.mapreduce.TaskCounter,它包含的計數器如下表所示:

計數器名稱 說明
map 輸入的記錄數(MAP_INPUT_RECORDS) 作業中所有 map 已處理的輸入記錄數。每次 RecorderReader 讀到一條記錄並將其傳給 map 的 map() 函數時,該計數器的值增加。
map 跳過的記錄數(MAP_SKIPPED_RECORDS) 作業中所有 map 跳過的輸入記錄數。
map 輸入的字節數(MAP_INPUT_BYTES) 作業中所有 map 已處理的未經壓縮的輸入數據的字節數。每次 RecorderReader 讀到一條記錄並 將其傳給 map 的 map() 函數時,該計數器的值增加
分片split的原始字節數(SPLIT_RAW_BYTES) 由 map 讀取的輸入-分片對象的字節數。這些對象描述分片元數據(文件的位移和長度),而不是分片的數據自身,因此總規模是小的
map 輸出的記錄數(MAP_OUTPUT_RECORDS) 作業中所有 map 產生的 map 輸出記錄數。每次某一個 map 的Context 調用 write() 方法時,該計數器的值增加
map 輸出的字節數(MAP_OUTPUT_BYTES) 作業中所有 map 產生的 未經壓縮的輸出數據的字節數。每次某一個 map 的 Context 調用 write() 方法時,該計數器的值增加。
map 輸出的物化字節數(MAP_OUTPUT_MATERIALIZED_BYTES) map 輸出後確實寫到磁盤上的字節數;若 map 輸出壓縮功能被啓用,則會在計數器值上反映出來
combine 輸入的記錄數(COMBINE_INPUT_RECORDS) 作業中所有 Combiner(如果有)已處理的輸入記錄數。Combiner 的迭代器每次讀一個值,該計數器的值增加。
combine 輸出的記錄數(COMBINE_OUTPUT_RECORDS) 作業中所有 Combiner(如果有)已產生的輸出記錄數。每當一個 Combiner 的 Context 調用 write() 方法時,該計數器的值增加。
reduce 輸入的組(REDUCE_INPUT_GROUPS) 作業中所有 reducer 已經處理的不同的碼分組的個數。每當某一個 reducer 的 reduce() 被調用時,該計數器的值增加。
reduce 輸入的記錄數(REDUCE_INPUT_RECORDS) 作業中所有 reducer 已經處理的輸入記錄的個數。每當某個 reducer 的迭代器讀一個值時,該計數器的值增加。如果所有 reducer 已經處理完所有輸入, 則該計數器的值與計數器 “map 輸出的記錄” 的值相同
reduce 輸出的記錄數(REDUCE_OUTPUT_RECORDS) 作業中所有 map 已經產生的 reduce 輸出記錄數。每當某一個 reducer 的 Context 調用 write() 方法時,該計數器的值增加。
reduce 跳過的組數(REDUCE_SKIPPED_GROUPS) 作業中所有 reducer 已經跳過的不同的碼分組的個數。
reduce 跳過的記錄數(REDUCE_SKIPPED_RECORDS) 作業中所有 reducer 已經跳過輸入記錄數。
reduce 經過 shuffle 的字節數(REDUCE_SHUFFLE_BYTES) shuffle 將 map 的輸出數據複製到 reducer 中的字節數。
溢出的記錄數(SPILLED_RECORDS) 作業中所有 map和reduce 任務溢出到磁盤的記錄數
CPU 毫秒(CPU_MILLISECONDS) 總計的 CPU 時間,以毫秒爲單位,由/proc/cpuinfo獲取
物理內存字節數(PHYSICAL_MEMORY_BYTES) 一個任務所用物理內存的字節數,由/proc/cpuinfo獲取
虛擬內存字節數(VIRTUAL_MEMORY_BYTES) 一個任務所用虛擬內存的字節數,由/proc/cpuinfo獲取
有效的堆字節數(COMMITTED_HEAP_BYTES) 在 JVM 中的總有效內存量(以字節爲單位),可由Runtime().getRuntime().totaoMemory()獲取。
GC 運行時間毫秒數(GC_TIME_MILLIS) 在任務執行過程中,垃圾收集器(garbage collection)花費的時間(以毫秒爲單位), 可由 GarbageCollector MXBean.getCollectionTime()獲取;該計數器並未出現在1.x版本中。
由 shuffle 傳輸的 map 輸出數(SHUFFLED_MAPS) 有 shuffle 傳輸到 reducer 的 map 輸出文件數。
失敗的 shuffle 數(SHUFFLE_MAPS) 在 shuffle 過程中,發生拷貝錯誤的 map 輸出文件數,該計數器並沒有包含在 1.x 版本中。
被合併的 map 輸出數 在 shuffle 過程中,在 reduce 端被合併的 map 輸出文件數,該計數器沒有包含在 1.x 版本中。

2.1.2 文件系統計數器

文件系統計數器的 groupName爲org.apache.hadoop.mapreduce.FileSystemCounter,它包含的計數器如下表所示:

計數器名稱 說明
文件系統的讀字節數(BYTES_READ) 由 map 和 reduce 等任務在各個文件系統中讀取的字節數,各個文件系統分別對應一個計數器,可以是 Local、HDFS、S3和KFS等。
文件系統的寫字節數(BYTES_WRITTEN) 由 map 和 reduce 等任務在各個文件系統中寫的字節數。

2.1.3 FileInputFormat 計數器

FileInputFormat 計數器的 groupName爲org.apache.hadoop.mapreduce.lib.input.FileInputFormatCounter,它包含的計數器如下表所示,計數器名稱列的括號()內容即爲counterName

計數器名稱 說明
讀取的字節數(BYTES_READ) 由 map 任務通過 FileInputFormat 讀取的字節數。

2.1.4 FileOutputFormat 計數器

FileOutputFormat 計數器的 groupName爲org.apache.hadoop.mapreduce.lib.input.FileOutputFormatCounter,它包含的計數器如下表所示

計數器名稱 說明
寫的字節數(BYTES_WRITTEN) 由 map 任務(針對僅含 map 的作業)或者 reduce 任務通過 FileOutputFormat 寫的字節數。

2.2 作業計數器

作業計數器由 JobTracker(或者 YARN)維護,因此無需在網絡間傳輸數據,這一點與包括 “用戶定義的計數器” 在內的其它計數器不同。這些計數器都是作業級別的統計量,其值不會隨着任務運行而改變。 作業計數器計數器的 groupName爲org.apache.hadoop.mapreduce.JobCounter,它包含的計數器如下表所示

計數器名稱 說明
啓用的map任務數(TOTAL_LAUNCHED_MAPS) 啓動的map任務數,包括以“推測執行” 方式啓動的任務。
啓用的 reduce 任務數(TOTAL_LAUNCHED_REDUCES) 啓動的reduce任務數,包括以“推測執行” 方式啓動的任務。
失敗的map任務數(NUM_FAILED_MAPS) 失敗的map任務數。
失敗的 reduce 任務數(NUM_FAILED_REDUCES) 失敗的reduce任務數。
數據本地化的 map 任務數(DATA_LOCAL_MAPS) 與輸入數據在同一節點的 map 任務數。
機架本地化的 map 任務數(RACK_LOCAL_MAPS) 與輸入數據在同一機架範圍內、但不在同一節點上的 map 任務數。
其它本地化的 map 任務數(OTHER_LOCAL_MAPS) 與輸入數據不在同一機架範圍內的 map 任務數。由於機架之間的寬帶資源相對較少,Hadoop 會盡量讓 map 任務靠近輸入數據執行,因此該計數器值一般比較小。
map 任務的總運行時間(SLOTS_MILLIS_MAPS) map 任務的總運行時間,單位毫秒。該計數器包括以推測執行方式啓動的任務。
reduce 任務的總運行時間(SLOTS_MILLIS_REDUCES) reduce任務的總運行時間,單位毫秒。該值包括以推測執行方式啓動的任務。
在保留槽之後,map任務等待的總時間(FALLOW_SLOTS_MILLIS_MAPS) 在爲 map 任務保留槽之後所花費的總等待時間,單位是毫秒。
在保留槽之後,reduce 任務等待的總時間(FALLOW_SLOTS_MILLIS_REDUCES) 在爲 reduce 任務保留槽之後,花在等待上的總時間,單位爲毫秒。

3. 自定義計數器使用

步驟:

  1. 定義枚舉類
  2. 拿到計數器context.getCounter()

現在有一份數據:lossData

hello	I	am	honey
hello	I	am	lily
hello	I	honey
hello	I	am	
hello	I	am	tiger

需求:現要求統計殘缺數據的條數
自定義計數器

MyCounter.java

public enum MyCounter {
    LOSS_FIELDS_DATA_RECORS
}

LossDataCount.java

/**
 * 統計殘缺字段的數據條數
 * map端:
 * 	獲取每一行數據   進行統計
 * 	這裏只是一個簡單統計,不需要reduce了
 * 	一般計數器也不會單獨使用,像mapreduce那些默認計數器,都是業務中使用人
 */
public class LossDataCount {
    static class LossDataCountMapper extends Mapper<LongWritable, Text, NullWritable, NullWritable>{

        /**
         *我們有一份數據,共4個字段,如果字段<4,我們就簡單認爲它是殘缺數據
         */
        @Override
        protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
            //hello	I	am	lily
            //hello	I	honey
            String[] datas = value.toString().split("\t");
            if(datas.length != 4){
                Counter counter = context.getCounter(MyCounter.LOSS_FIELDS_DATA_RECORS);
                /**
                 * Counter爲我們提供了一些方法
                 * String getName();  獲取計數器名字
                 * long getValue();  獲取計數器的值
                 * void setValue(long value);  給計數器設置值
                 * void increment(long incr);   將計數器自增  ++
                 */
                //計數器+1
                counter.increment(1l);
            }
        }
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        System.setProperty("HADOOP_USER_NAME","hdp01");
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS","hdfs://10.211.55.20:9000");

        Job job=Job.getInstance(conf);

        job.setJarByClass(LossDataCount.class);

        job.setMapperClass(LossDataCountMapper.class);

        job.setOutputKeyClass(NullWritable.class);
        job.setOutputValueClass(NullWritable.class);
        job.setNumReduceTasks(0);
        FileInputFormat.addInputPath(job, new Path("/tmpin/lossData"));
        FileOutputFormat.setOutputPath(job, new Path("/tmpout/counter/out1"));
        job.waitForCompletion(true);
		//獲取計數器的值
		Counters counters = job.getCounters();
        Counter counter = counters.findCounter(MyCounter.LOSS_FIELDS_DATA_RECORS);
        System.out.println("自定義計數器的值---->"+counter.getName()+"="+counter.getValue());
    }
    
}

因爲我們沒有reduce,看輸出結果:

[hdp01@hdp01 tmpfiles]$ hdfs dfs -ls /tmpout/counter/out1
Found 2 items
-rw-r--r--   3 hdp01 supergroup          0 2019-12-21 16:54 /tmpout/counter/out1/_SUCCESS
-rw-r--r--   3 hdp01 supergroup          0 2019-12-21 16:54 /tmpout/counter/out1/part-m-00000
[hdp01@hdp01 tmpfiles]$ hdfs dfs -cat /tmpout/counter/out1/part-m-00000
內容爲空

那麼我們的計數器,技術統計到哪了呢?看控制檯部分輸出

19/12/21 16:57:53 INFO mapreduce.Job: Counters: 21  一共有21個計數器
	File System Counters
		FILE: Number of bytes read=160
		FILE: Number of bytes written=293886
		FILE: Number of read operations=0
		FILE: Number of large read operations=0
		FILE: Number of write operations=0
		HDFS: Number of bytes read=77
		HDFS: Number of bytes written=0
		HDFS: Number of read operations=7
		HDFS: Number of large read operations=0
		HDFS: Number of write operations=3
	Map-Reduce Framework
		Map input records=6
		Map output records=0
		Input split bytes=104
		Spilled Records=0
		Failed Shuffles=0
		Merged Map outputs=0
		GC time elapsed (ms)=0
		Total committed heap usage (bytes)=188219392
	com.study.follow.counter.MyCounter  我們統計的殘缺數據量
		LOSS_FIELDS_DATA_RECORS=3
	File Input Format Counters 
		Bytes Read=77
	File Output Format Counters 
		Bytes Written=0

自定義計數器的值---->LOSS_FIELDS_DATA_RECORS=3
		
發佈了84 篇原創文章 · 獲贊 12 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章