【MapReduce】Mapreduce基础知识整理 (六) 全局计算器

文章目录

  • 1. 什么是全局计数器
  • 2. 常用全局计数器
    • 2.1 任务计数器
      • 2.1.1 MapReduce 任务计数器
      • 2.1.2 文件系统计数器
      • 2.1.3 FileInputFormat 计数器
      • 2.1.4 FileOutputFormat 计数器
    • 2.2 作业计数器
  • 3. 自定义计数器使用

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
		

你可能感兴趣的:(Hadoop)