一、mapreduce编程规范
用户编写mr程序主要分为三个部分:Mapper,Reducer,Driver
1.Mapper阶段
(1)用户自定义mapper类 要继承父类Mapper
(2)Mapper的输入数据的kv对形式(kv类型可以自定义)
(3)Mapper的map方法的重写(加入业务逻辑)
(4)Mapper的数据输出kv对的形式(kv类型可以自定义)
(5)map()方法(maptask进程)对每个<k,v>调用一次
2.Reducer阶段
(1)用户自定义reducer类 要继承父类Reducer
(2)Reducer的数据输入类型对应的是Mapper阶段的输出数据类型,也是kv对
(3)Reducer的reduce方法的重写(加入业务逻辑)
(4)ReduceTask进程对每组的k的<k,v>组调用一次reduce方法
3.Driver阶段
mr程序需要一个Driver来进行任务的提交,提交的任务是一个描述了各种重要信息的job对象
二、常用数据序列化类型
JAVA 类型 HADOOP 类型
int IntWritable
float FloatWritable
long LongWritable
double DoubleWritable
string Text
boolean BooleanWritable
byte ByteWritable
map MapWritable
array ArrayWritable
为什么要序列化?
存储“活的对象”
1、作为一种持久化格式。
2、作为一种通信的数据格式。
3、作为一种数据拷贝、克隆机制。
什么是序列化?
序列化就是把内存当中的对象,转换成字节序列以便于存储和网络传输
反序列化就是将受到的字节序列或者硬盘的持久化数据,转换成内存中的对象
java的序列化->Serializable
为什么不使用java提供的序列化接口?
java的序列化是一个重量级的序列化框架,一个对象被序列化后会附带很多额外信息(效验信息,header,继承体系等)。
不便于在网络中高效传输,所以hadoop开发了一套序列化机制(Writable),精简/高效.
为什么序列化在hadoop中很重要?
hadoop通信是通过远程调用(rpc)实现的,需要进行序列化。
特点:
1)紧凑
2)快速
3)可拓展
4)互操作
三、WordCount(mapreduce)代码
例子预处理文件word.txt,word1.txt,数据如下:
word.txt
hello reba
hello lizi
hello wanglikun
heihei reba
heihei yangmi
haha likun
hello world
word1.txt
aa bb cc
bb tt dd
cc
cc
WordCountMapper
/**
* wordCount单词计数
* @author chengguo
* @date 2019年1月8日下午1:52:39
* @version 1.0
*
* KEYIN:数据起始偏移量
* VALUEIN:数据
*
* KEYOUT:mapper输入到reduce阶段k的类型
* VALUEOUT:mapper输入到reduce阶段v的类型
*/
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
//key 起始偏移量 value 数据 context 上下文
@Override
protected void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
//1.读数据
String line = value.toString();
//2.切割
String[] words = line.split(" ");
//3.循环的写到下一个阶段
for(String w:words) {
//4.输出到reducer阶段
context.write(new Text(w), new IntWritable(1));
}
}
}
WordCountReducer
/**
* 汇总
* @author chengguo
* @date 2019年1月8日下午2:04:21
* @version 1.0
*/
public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable>{
/**
* 汇总操作
*/
@Override
protected void reduce(Text key, Iterable<IntWritable> values,
Context context) throws IOException, InterruptedException {
//1.统计单词出现的次数
int sum = 0;
//2.累加求和
for(IntWritable count:values) {
sum += count.get();
}
//3.结果输出
context.write(key, new IntWritable(sum));
}
WordCountDriver
public class WordCountDriver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
//1.获取job信息
Configuration conf = new Configuration();
Job job = Job.getInstance(conf);
//2.获取jar包
job.setJarByClass(WordCountDriver.class);
//3.获取自定义的mapper和reducer类
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
//4.设置map输出的数据类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
//5.设置reduce输出的数据类型(最终的数据类型)
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//6.设置数据存在的路径与处理后的结果路径
FileInputFormat.setInputPaths(job, new Path("C:/BIGDATA/Test/sin"));
FileOutputFormat.setOutputPath(job,new Path("C:/BIGDATA/Test/sout"));
//7.提交任务
boolean rs = job.waitForCompletion(true);
System.out.println(rs?0:1);
}
}
处理结果
aa 1
bb 2
cc 3
dd 1
haha 1
heihei 2
hello 4
likun 1
lizi 1
reba 2
tt 1
wanglikun 1
world 1
yangmi 1
四、WordCount任务集群提交
修改后的Driver
public class WordCountDriver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
//1.获取job信息
Configuration conf = new Configuration();
Job job = Job.getInstance(conf);
//2.获取jar包
job.setJarByClass(WordCountDriver.class);
//3.获取自定义的mapper和reducer类
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
//4.设置map输出的数据类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
//5.设置reduce输出的数据类型(最终的数据类型)
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//6.设置数据在hdfs上存在的路径与处理后的结果路径
FileInputFormat.setInputPaths(job, new Path("/wc/in"));
FileOutputFormat.setOutputPath(job,new Path("/wc/out"));
//7.提交任务
boolean rs = job.waitForCompletion(true);
System.out.println(rs?0:1);
}
}
项目打成jar包,上传集群
记得修改mapred-site.xml文件。
<property>
<name>mapreduce.framework.name</name>
<value>local</value>
<description>The runtime framework for executing MapReduce jobs.
Can be one of local, classic or yarn.
</description>
</property>