Hadoop之MapReduce
定义:分布式运算程序的编程框架
核心功能:将用户编写的业务逻辑代码和自带组件整合成一个分布式运算程序,并发运行在hadoop集群上
优点:高容错,任务计算失败会重启4次
适合离线数据
缺点:不善于实时和流式计算即有(DAG)向图计算:
思想就是多个MR串联,不断的进行输入输出到下一个MR,耗费资源,不太擅长此类计算
MapReduce核心编程思想(中间有一个排序的过程)
计算角度切片,存储角度块
1)Map阶段,以workcount程序为例
1.读数据,按行处理
2.按空格切分行内单词
3.kv键值对(单词,1)
4.将所有kv值对中单词,按单词首字母,分成2个分区溢写到磁盘
2)Reduce阶段
1.分别统计2个分区的汇总
2.分别输出到文件
MapReduce进程
1.MrAppMaster(子)本质就是yarn的applicationMaster(父),1个
2.MapTask:个数由多少个任务决定
3.ReduceTask:个数由计算分区决定
官方wordcount源码
找到jar包中的example的jar包,用资料里的反编译软件进行反编译
常用数据类型 和 mapreduce的数据类型对应
String>-Text
其他加Writable即可
MapReduce编程规范
Mapper, Reducer,Driver
1)Mapper阶段:继承自己的父类,输入数据是KV对形式,业务逻辑写在mpa()方法中,输出也是KV对,map()方法(MapTask进程)对每个kv调用一次
2Reducer阶段:继承自己的父类,输入/出是KV对,逻辑写reduce()方法中,reduce()方法(reduceTask进程)对每个kv调用一次
3)Driver:有本地和集群模式,相当与yarn集群的客户端,提交程序到yarn集群
-7mapreduce案例编写mapper
1)设置自定义wordcountmapper extend mapper<Longwritable,Txet(输入的kv),text,Intwritable(输出的kv)>
2)重写map方法
读取一行 输入的Text的kv对的value:
String line =value.toString;
把读到的按空格分隔单词:
String [] words=line.split(" ");
设置每个单词的配置到输出kv对里面:
遍历数组words for(String word: words){
k.set(word);
context(k,v(设置为1));
}
value个数默认为1个
-8mapreduce案例编写reducer
1)设置自定义的wordcountreducer extend reducer
<Text,IntWritable(mapper的输出),Text,Intwritable(reducer的最终输出)>(<k,v,k,v >)
遍历reduce中的输入迭代器
sum=0;
for(Iteable: values){
sum+count.get();
}
v.set(sum);
-9mapreduce案例编写Driver
1)自定义主方法main(){
1.创建job对象:job.getinstanc();
2.自定义配置对象Configuration conf = new Configuration();
3.设置jar类的加载 :job.setjarbyclass();
4.设置mapper和ruducer的类: job.setMapperclass(wordcountmapper.class) .etc略
5.设置map输出类:job.setMapOutputKeyclass(Text.class);
6设置最终输出类:job.setOutputKeyClass(Text.class);
7设置输入路径和输出路径FileInputFormat.setInputPaths(job,new Path("args[0]"))
8提交job:job.waitForCompletion(true)
}
-10mapreduce案例编写的执行方式
1)IDEA中java本地测试
FileInputFormat.setInputPaths(job,
new Path("D:\\Develop\\AiStocker\\hello1.txt"));
FileOutputFormat.setOutputPath(job,
new Path("D:\\Develop\\AiStocker\\output"));
2)集群上测试
moven上打成jar包,直接拖到shell软件中的Hadoop_Home目录中即可
执行命令:hadoop jar 包的的路径 驱动类所在的jar包里面所在packet包的全路径 设置的输入路径 设置的输出路径
3)windows上向集群提交任务
在上面代码中添加以下信息后打包,并将jar包设置到Driver中
//设置HDFS NameNode的地址
configuration.set("fs.defaultFS", "hdfs://hadoop102:8020");
// 指定MapReduce运行在Yarn上
configuration.set("mapreduce.framework.name","yarn");
// 指定mapreduce可以在远程集群运行
configuration.set("mapreduce.app-submission.cross-platform","true");
//指定Yarn resourcemanager的位置
configuration.set("yarn.resourcemanager.hostname","hadoop103");
打包后,设置到Driver中,即修改job.setJarByClass为jobsetJar("jar包的在本地磁盘的物理路径")
编辑后在窗口右上角修改下拉框中的Edit Configuration,设置VM options 为 -DHADOOP_USER_NAME=指定集群用户名
Program arguments 改为 hdfs://hadoop102:8020/hdfs文件目录的文件输入路径 hdfs://Hadoop102:8020/hdfs文件目录的文件输出路径
-13序列化
为何要序列化:序列化可以存储活的对象,并发送活的对象到远程计算机,不怕断电,在内存中丢失
1)java中的序列化要实现serializable接口.
java中的serialVersionUID为了保证序列化和反序列化的数据的安全
通过ObejectOutputStreame中的writeObject即readObject实现序列化反序列化
2)hadoop的序列化
1.需要支持序列化的类要实现Wriable接口
提供无参构造器(反序列化时通过反射的方式调用无参构造器构造对象)
重写write,实现序列化
重写readFields,实现反序列化
序列化和反序列化顺序要一致
一般会重写toString方法,将结果对象写入最终文件里面,会调用对象的toString进行打印
Driver的JOB对象要实例化后设置值
MapReduce框架原理
MapRecuce的流程:map阶段和reduce阶段
详细:数据输入(InputFormat)-->Mapper-->shuffle-->Reducer-->数据输出(OutputFormat)
源码:map阶段(map+sort)+reduce阶段(copy+sort+reduce)
copy是因为map输出后会落盘,因为map和reduce不能保证在同一台机器运行,所以落盘后复制过去运行
sort+copy+sort 大概就是shuffle的阶段内容
1)inputFormat(数据输入)
数据输入切片,处理输入数据可以识别的
2)shuffle洗牌机制
mapper输出context后到reducer之间进行处理洗牌
3)outputFormat(数据输出)
reducer输出经过outputFormat进行写出
InputFormat的源码
切片
1)概念:计算时的概念
数据块:是数据在HDFS中存储的基本单元.是从物理上将原始数据进行分块.
数据切片:数据在MR中计算的基本单元,是从逻辑上将原始数据进行切片操作,
实际上每个切片就是来记录应该从哪个位置读取到哪个位置
读取时是整体数据读取再切片,而不是按块里面取切片
2)切片与MapTask
切片个数决定MapTask的个数.
如果每个MapTask处理的数据量是比较合适的,MapTask越多越好
单个文件单独切片
3)切片的大小
默认情况下,切片的大小等于块的大小,避免跨机器读取数据切片
4)FileInput
Shuffle的源码机制?
-8分区
获取分区器对象mapTask711行
大于1,读取配置paririoneer.calss获取,获取不到就使用Hashpatrutionner分区器
11-MapReduce排序?
1)java排序
Comparable-->compareTo()
Comparator-->compare()
2)hadoop的排序
Writablecomparable-->
writablecompare-->
13-全排序实例操作
14-分区排序实例
1回顾
2-Combiner
1)继承了reducer,是MR程序中Mapper和Reducer之外的一种组件
2)combiner在每一个MapTask节点运行,Reducer接收全局所有的Mapper输出结果
3)意义是对Mapper输出局部汇总,减少网络传输,应用前提是不能影响最终业务逻辑
具体实现就是自定义Combiner类继承reducer,实现reduce方法,
在job设置job.setCombinerClass(wordCounterReducer.class)
分组
1)reducer端将数据copy过来,进行归并排序,进入reduce方法时,进行分组
2)分组操作就是reduce方法处理数据过程进行的,每读取一个kv,预读下一个kv,并判断下个kv跟当前kv是否相同(是否是一组)
3)Hadoop如何进行分组比较
ReducerTask'
Hadoop会通过group.coomparator获取分组比较器
能获取,则用,获取不到,则尝试获取排序比较器,往后处理,参考获取排序比较器的过程
-6分组比较案例分组比较器
如何分组后取到id中的第一个最大的值?
-7OutputFormat输出 介绍
1)
2)自定义OutputFormat

浙公网安备 33010602011771号