map阶段将要处理的任务切分成一个个的MapTask,每个MapTask各自计算自己负责计算的内容,也就是将计算分布式。
map阶段有两步:
1.设置TextInputFormat类,将数据切分为
2.自定义Map逻辑,将第一步的结果转化为
1.对输出的
2.对不同分区的数据按照相同的key排序
3.对分组的数据初步规约,降低数据的网络拷贝
4.对数据分组,相同的key的value放在一个集合中
注意:在编程中,如果不写shuffle代码,会采用默认的分区分组方法。因此在实际工程中更具需求此处是可选的。
Reduce将上面的MapTask和Shuffle的计算结果进行整合得到最终输出。
Reduce有两步:
1.对多个 Map 任务的结果进行排序以及合并, 编写 Reduce 函数实现自己的逻辑, 对输 入的 Key-Value 进行处理, 转为新的 Key-Value(K3和V3)输出。
2.设置 TextOutputFormat 处理并保存 Reduce 输出的 Key-Value 数据
首先确保hadoop集群能正常启动(dfs集群和yarn集群),然后准备一份文本上传到hdfs中。这里不在赘述。
hdfs_api
com.sora
1.0-SNAPSHOT
../hdfs_api/pom.xml
jar
4.0.0
mapreduce
org.apache.hadoop
hadoop-common
3.0.0
provided
org.apache.hadoop
hadoop-hdfs
3.0.0
org.apache.hadoop
hadoop-hdfs-client
3.0.0
provided
org.apache.hadoop
hadoop-client
3.0.0
junit
junit
4.12
test
org.apache.maven.plugins
maven-shade-plugin
2.4.3
org.junit.jupiter
junit-jupiter-api
RELEASE
compile
注意一定要添加packaging,因为要打包到linux服务器中执行。
package com.sora.mapreduce;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;
/**
*Mapper泛型:
* KEYIN K1的类型 行偏移量 LongWritable
* VALUEIN v1的类型 行文本数据 Text
* KEYOUT K2的类型 一个单词 Text
* VALUEOUT v2的类型 固定值 1 LongWritable
* **/
/**
* map function:将k1和v1转化成k2和v2
* k1 v1 k2 v2
* 0 hello,world hello 1
* 11 hello,hadoop world 1
* hello 1
* hadoop 1
* **/
public class WordCountMapper extends Mapper {
/**
* key - k1 value - v1 context - mapreduce上下文对象:连接map和reduce
* **/
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
Text text = new Text();
LongWritable longWritable = new LongWritable();
//对每一行的数据字符串拆分
String line = value.toString();
String[] split = line.split(",");
//遍历数组 获取每一个单词
for(String word:split){
text.set(word);
longWritable.set(1);
context.write(text,longWritable);
}
}
}
package com.sora.mapreduce;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
/**
* KEYIN k2 Text 每个单词
* VALUEIN V2 LongWritable 集合中泛型的类型
* KEYOUT K3 Text每个单词
* VALUEOUT V3 LongWritable 每个单词出现的次数
* **/
/**
* reduce 将k2 v2 转为k3 v3
* k2 v2 k3 v3
* hello <1,1> hello 2
* world <1,1> world 2
* hadoop <1,1,1> hadoop 3
* **/
public class WordCountReducer extends Reducer{
/**
* key K2
* values 集合
* context mapreduce的上下文对象
* **/
@Override
protected void reduce(Text key, Iterable values, Context context) throws IOException, InterruptedException {
long count = 0;
LongWritable longWritable = new LongWritable();
//遍历values集合
for (LongWritable value:values){
//将集合中的值相加
count += value.get();
}
longWritable.set(count);
//将k3 v3 写入上下文中
context.write(key, longWritable);
}
}
package com.sora.mapreduce;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
public class JobMain extends Configured implements Tool {
//串联mapreduce的整个过程 map shuffle reduce
public int run(String[] strings) throws Exception {
//创建一个任务对象
Job job = Job.getInstance(super.getConf(), "mapreduce_wordcount");
//打包在集群中运行 需要做配置
job.setJarByClass(JobMain.class);
//1.设置读取文件的类: 生成k1 v1
job.setInputFormatClass(TextInputFormat.class);
TextInputFormat.addInputPath(job, new Path("hdfs://192.168.159.128:8020/worldcount"));
//2.设置mapper类
job.setMapperClass(WordCountMapper.class);
//设置mapper阶段输出类型 k2 v2
job.setMapOutputKeyClass(Text.class);
job.setOutputValueClass(LongWritable.class);
//3.4.5.6采用默认分区,排序,规约,分组
//7.设置reduce类
job.setReducerClass(WordCountReducer.class);
//设置reduce阶段的输出类型 k3 v3
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(LongWritable.class);
//8.设置输出类型
job.setOutputFormatClass(TextOutputFormat.class);
//设置输出路径
TextOutputFormat.setOutputPath(job, new Path("hdfs://192.168.159.128:8020/wordcount_out"));
boolean b = job.waitForCompletion(true);
return b?0:1;
}
public static void main(String[] args) throws Exception {
Configuration configuration = new Configuration(); //配置对象 放配置信息
//启动任务
int run = ToolRunner.run(configuration, new JobMain(), args);//调用上面的重写的run方法
}
}
6.打成jar包上传到hadoop的主节点服务器,(namenode和resoucemanager的那台节点),然后执行hadoop命令:
hadoop jar wordcount.jar com.sora.mapreduce.JobMain
成功后在hdfs中就会有输出文件。大家自己试一试吧 亲测有效!