MapReduce计数器计数

来源:互联网 发布:剑灵捏脸数据免费的 编辑:程序博客网 时间:2024/06/07 08:38

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个

0 0