MapReduce计数器计数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wcandy001/article/details/49814281

MapReduce框架自身就有计数机制跟中输入记录的数量,并且所有的计数器信息都存在JobTracker的内存中,在每个map任务中计数器被序列化,并通过状态更新同步到JobTracker,也就是说各节点的计数器结果会在JobTracker进行汇总

适用场景:大数据集收集指定字符的出现次数

运行环境:windows下VM虚拟机,centos系统,hadoop2.2.0,三节点 ,java 1.7

例子:查找数据中AA,BB,CC,DD的数据行,并计数
数据:
AA
BB
CC
DD
AA
CC
DD
EE
BB
AA
CC
DD
OO
EE
CC
AA
CC
BB
EE
ZZ

public class CounterNumber extends Configured implements Tool{
        //这个任务中不需要输出结果,直接打印在控制台上
    public static class Map extends Mapper <LongWritable,Text,NullWritable,NullWritable>
    {
    //指定要计数的目标字符串数组
        private String[] str={"AA","BB","CC","DD"};
        //指定标志,成功,失败
        private static final String STATE_TRUE="State";
        private static final String STATE_FALSE="unknow";
        public void map(LongWritable key,Text value,Context context)throws InterruptedException,IOException
        {
        //设定标志,用于没匹配到的记录的计数
            boolean sign=true;
            //遍历目标数组
            for(String str1 :str)
            {
            //如果输入的一条记录中有目标数组
                if(value.toString().contains(str1))
                {
                //getCounter是设定框架的计数器,参数为(标志,具体目标),increments(1)是把计数器加1
                    context.getCounter(STATE_TRUE, str1).increment(1);;
                    sign=false;
                    break;
                }
            }
            //如果这条记录没找到匹配到目标
            if(sign)
            {
            //创建一个计数器用于记录没匹配到的数量
                context.getCounter(STATE_FALSE, "unknow_str").increment(1);
            }
        }
    }
    public int run (String[] args)throws Exception
    {
        Configuration conf=getConf();
        Job job=new Job(conf,"CounterNumber");
        job.setJarByClass(CounterNumber.class);
        job.setMapperClass(Map.class);
        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));
        job.setOutputKeyClass(NullWritable.class);
        job.setOutputValueClass(NullWritable.class);
        //这句是提交任务的
        int code=job.waitForCompletion(true)?1:0;
        //在任务提交后获取任务counter信息
        if(code==1)
        {
        //获取指定计数器信息
            for (Counter counter:job.getCounters().getGroup(Map.STATE_TRUE))
            {
            //输出计数器的目标名字和数量
                System.out.println(counter.getDisplayName()+"\t"+counter.getValue());
            }
        }
        return job.isSuccessful()?1:0;
    }
    public static void main(String[] args)throws Exception
    {
        int rsa=ToolRunner.run(new Configuration(), new CounterNumber(), args);
        System.exit(rsa);
    }
}

执行结果
这里写图片描述
可以看出mapreduce本身就已经记录了计数器的状态(后面的红色部分)
这种方法的计数效率非常高,因为数据只是在map进行读入,没有大量IO交互

计数器数量的不宜过大,以为都要写入JobTracker的内存中,最多不超过100个,这里用了5个

猜你喜欢

转载自blog.csdn.net/wcandy001/article/details/49814281