Hadoop(MapReducer)

MapReduce 进程
一个完整的 mapreduce 程序在分布式运行时有三类实例进程:
1)MrAppMaster:负责整个程序的过程调度及状态协调。
2)MapTask:负责 map 阶段的整个数据处理流程。
3)ReduceTask:负责 reduce 阶段的整个数据处理流程。

MapReduce编程规范
用户编写的程序分成三个部分:Mapper,Reducer,Driver(提交运行 mr 程序的客户端)
1)Mapper 阶段
(1)用户自定义的 Mapper 要继承自己的父类
(2)Mapper 的输入数据是 KV 对的形式(KV 的类型可自定义)
(3)Mapper 中的业务逻辑写在 map()方法中
(4)Mapper 的输出数据是 KV 对的形式(KV 的类型可自定义)
(5)map()方法(maptask 进程)对每一个调用一次
2)Reducer 阶段
(1)用户自定义的 Reducer 要继承自己的父类
(2)Reducer 的输入数据类型对应 Mapper 的输出数据类型,也是 KV
(3)Reducer 的业务逻辑写在 reduce()方法中
(4)Reducetask 进程对每一组相同 k 的组调用一次 reduce()方法
3)Driver 阶段
整个程序需要一个 Drvier 来进行提交,提交的是一个描述了各种必要信息的 job 对象

为什么序列化对 Hadoop 很重要?
因为 Hadoop 在集群之间进行通讯或者 RPC 调用的时候,需要序列化,而且要求序列
化要快,且体积要小,占用带宽要小。所以必须理解 Hadoop 的序列化机制。
序列化和反序列化在分布式数据处理领域经常出现:进程通信和永久存储。然而 Hadoop
中各个节点的通信是通过远程调用(RPC)实现的,那么 RPC 序列化要求具有以下特点:
1)紧凑:紧凑的格式能让我们充分利用网络带宽,而带宽是数据中心最稀缺的资
2)快速:进程通信形成了分布式系统的骨架,所以需要尽量减少序列化和反序列化的
性能开销,这是基本的;
3)可扩展:协议为了满足新的需求变化,所以控制客户端和服务器过程中,需要直接
引进相应的协议,这些是新协议,原序列化方式能支持新的协议报文;
4)互操作:能支持不同语言写的客户端和服务端进行交互;

Hadoop(MapReducer)_第1张图片
Hadoop(MapReducer)_第2张图片

package mapreduce;

import java.io.IOException;
import java.util.Map;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.mapreduce.Mapper;

import  org.apache.hadoop.io.Text;

/**
 * 	输入的key  LongWritable  行号
 * 	输入的value	Text	一行内容
 * 	输出的key	Text		单词
 * 	输出的value	IntWritable	单词的个数
 * 
 * 	Mapper  前两个是输入的  后两个是输出的
 * 
 * 
 */
public class DataMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
	Text k = new Text();
	IntWritable v = new IntWritable(1);
//	hello world
//	hadoop
//	spark
	@Override
	protected void map(LongWritable key, Text value, Context context)
			throws IOException, InterruptedException {
		
		//1.	一行内容转换成String
		String line = value.toString();
		
		//2.	切割
		String[] words = line.split(" ");
		
		//3.	循环写出到下一个阶段
		for(String word: words) {
			//这是输出的 K 和 V
			//因为输出的时候  K 是Text 类型  V 是 Int类型
			//context.write(new Text(word), new IntWritable(1));  
			//这样的话  太耗费资源了 每次都要new 
			//所以在外面我们直接创建一个Text k  IntWritable v 
			k.set(word);
			context.write(k,v);
		}
	}
}

```c
package mapreduce;

import java.io.IOException;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.io.Text;


/*
 *	前两个是输入   后两个是输出
 *	Reducer 的输入 就是 Mapper的输出
 */
public class DataReducer extends Reducer<Text, IntWritable, Text, IntWritable>{

//	hello world
//	hello world

//	hello 1
//	hello 1
//	world 1
//	world 1  等等····
	//把相同的key(比如hello) 都传到key里面去    把这些1都传进去 进行迭代   输出靠text
	@Override
	protected void reduce(Text key, Iterable<IntWritable> values,
			Context context) throws IOException, InterruptedException {
		//1.	统计单词总个数   那么就要遍历values
		int sum = 0;   //进行累加
		for(IntWritable count: values) {
			sum += count.get();
		}
		//2.	输出单词总个数
		context.write(key, new IntWritable(sum));

	}

}
package mapreduce;

import java.io.IOException;

import javax.sound.midi.Patch;

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;

/**
 * 	把Mapper 和 Reducer  组装起来 或者 组合起来
 * 
 * 	测试这个代码 就是 把这个打成一个Jar包  运行在集群jar上面
 * 	也可以采用本地运行的模式
 */
public class DataDriver {
	public static void main(String[] args) throws Exception {
		//1.	或者job信息
		Configuration configuration = new Configuration();
		Job job = Job.getInstance(configuration);
		
		//2.	获取jar包位置
		job.setJarByClass(DataDriver.class);
		
		//3.	关联自定义的mapper和reducer
		job.setMapperClass(DataMapper.class);
		job.setReducerClass(DataReducer.class);
		
		//4.	设置map输出数据类型
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(IntWritable.class);
		
		//5.	设置最终输出数据类型
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(IntWritable.class);
		
		//6.	设置数据输入和输出文件路径
		FileInputFormat.setInputPaths(job, new Path(args[0]));
		FileOutputFormat.setOutputPath(job, new Path(args[1]));
		
		//7.	提交代码
		// job.submit(); 提交过后完事了
		//	下面这个是等待结束0
		boolean result = job.waitForCompletion(true);
		System.exit(result ? 0 : 1);
	}
}

你可能感兴趣的:(MapReduce)