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个