MapReduce
MapReduce是一种可用于数据处理的编程模型。
Hadoop可以运行各种语言版本的MapReduce程序。
MapReduce程序本质上是并行运行的,因此可以将大规模的数据分析任务分发给任何一个拥有足够多机器的数据中心。
MapReduce的优势在于处理大规模数据集。
map和reduce
MapReduce任务过程分为两个处理阶段:map阶段和reduce阶段。
每阶段都以键-值对作为输入和输出,其类型由程序员来选择。程序员还需要写两个函数:map函数和reduce函数。
MapReduce对数据的处理:都是以键值对<key,value>的形式
(input) <k1, v1> -> map -> <k2, v2> -> reduce -> <k3, v3> (output)
编写MapReduce程序(单词统计)
- 创建java项目,导入jar包
- 编写map函数
import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
/*
* Mapper类型是一个泛型类型:
* Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT>
* 有四个形参类型,分别指定
* map函数的输入键、输入值、输出键、输出值的类型
*
* 单词统计案例:
* KEYIN: 行偏移量LongWritable
* VALUEING: 一行数据Text
* KEYOUT: 单词 Text
* VALUEOUT: 单词的数据IntWritable
*
*
* hello world welcome to china <0,"hello world welcome to china"> -----> <"hello",1> <"world","1">
* hello kitty <29,"hello kitty"> -----> <"hello",1> <"kitty",1>
*
*/
public class MyMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
private Text word = new Text();
private final IntWritable one = new IntWritable(1);
@Override
protected void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
//将一行数据进行切分,把多个单词封装到StringTokenizer对象内部,就是一个迭代器
StringTokenizer sti = new StringTokenizer(value.toString()," ");
//判断是否还有下一个单词
while(sti.hasMoreTokens()){
//从迭代器中取出一个单词,并将它转成Text类型
String str = sti.nextToken();
word.set(str);//word是Text类型
//将key和value输出
context.write(word, one);
}
}
}
- 编写reduce函数
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
/*
* Reducer<KEYIN,VALUEIN,KEYOUT,VALUEOUT>
*
*
* KEYIN:Text 单词作为key map阶段的输出数据key类型
* VALUEIN:IntWritable 单词的数量value: map阶段的输出数据value类型
* KEYOUT:Text 单词作为key
* VALUEOUT:IntWritable 单词最总统计数量
*
* 在接收map的输出数据后,进入reduce方法前,做了一次处理:将同一个key的value值放到一起组成新的键值对
*/
public class MyReducer extends Reducer<Text, IntWritable, Text, IntWritable>{
private IntWritable result = new IntWritable();
@Override
protected void reduce(Text key, Iterable<IntWritable> value,
Context context) throws IOException, InterruptedException {
//累加当前key的所有value值
int sum = 0;
for(IntWritable i : value){
sum+=i.get();
}
//将累加的value的值封装到IntWritable对象上
result.set(sum);
//写出输出数据,存入文件系统
context.write(key, result);
}
}
- 编写driver类[main方法]
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class MyWordCount {
public static void main(String[] args) throws Exception, Exception {
//获取一些配置信息
Configuration conf = new Configuration();
//获取一个作业对象
Job job = Job.getInstance(conf, "wordcount");
//设置执行jar包内的哪个类型[含有main方法的类型]
job.setJarByClass(MyWordCount.class);
//设置map函数的位置
job.setMapperClass(MyMapper.class);
//设置reduce函数的位置
job.setReducerClass(MyReducer.class);
//设置reduce阶段key的输出类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//设置要访问的文件的位置
FileInputFormat.addInputPath(job, new Path(args[0]));
//设置生成文件的位置
FileOutputFormat.setOutputPath(job, new Path(args[1]));
//打印报告
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
打包mapreduce程序
点击项目,右键选择export---->java---->jar file---->选择你要导出的项目下的哪个包---->next---->设置 mainClass---->选择生成路径---->*.jar
注意:lib文件夹不要选择
上传到某一个Linux节点上
运行mapreduce程序
[wyc@master ~]$ hadoop jar *.jar [input path] [output path]
注意:output path的目录应该指定一个新目录,运行程序时,会自动创建这个路径
查看统计信息