MapReduce的概述
-
学习MapReduce的意义
1、面试需求 2、MR是分布式计算的鼻祖,理解分布式计算的思想和架构 3、HiveSQL底层默认就是MR 4、很多的分布式计算引擎都借鉴了MapReduce
-
大数据计算引擎的发展
第一代:MapReduce ---> IO硬盘 + 网络 第二代:Tez ---> IO硬盘 + 网络 + DAG 第三代:Spark ---> 内存 + 网络 + DAG 第四代:Flink ---> 内存
-
MapReduce思想
1、MapReduce会将一个大的计算任务进行拆分,拆分成小任务,让这些小任务在不同的计算机中进行处理,最后再将这些小任务的结果记性整体汇总 2、MapReduce分为两个阶段,一个Map阶段负责任务的拆分,一个是Reduce阶段,负责任务的汇总 3、整个MapReduce工作流程可以分为3个阶段:map、shuffle、reduce。
MapReduce编程
-
代码运行
hadoop jar moudle03_mapreduce-1.0-SNAPSHOT.jar pack01_wordcount_base.WordCountDriver hadoop jar moudle03_mapreduce-1.0-SNAPSHOT.jar hadoop jar moudle03_mapreduce-1.0-SNAPSHOT.jar /input /output/wordcount
MapReduce的shuffle阶段
(重点)分区
- 概念
1、分区就是分文件,本质是将不同的键值对,最后输出的不同的文件中,理解为将数据进行拆分
2、实现的方式是;在Map阶段对k2打标记,标记相同的数据就会分到同一个分区,同一个分区的数据会被同一个redue拉取
if(id % 2 == 0){
return 0;
}else{
return 1;
}
3、如果设置了分区则会有多个文件输出,则需要有多个reduce,相同标记的K2数据会被同一个reduce
处理,多个reduce就会产生多个结果文件
4、partition原来就是map结束之后根据key值不同,自定义打个标签。。。然后再由不同的reducer拉一下。。
-
编程
-
准备数据
日期 县 州 县编码 确诊人数 死亡人数 2021-01-28,Autauga,Alabama,01001 , 5554 , 69 =需求:将每一个州的疫情数据分到不同的文件中
-
编程步骤
1、编写Mapper类 2、编写自定义分区类 2.1 自定义分区类,继承Partitioner类,在该类中重写getPartition方法,制定分区规则(给K2打标记) 3、编写Reducer类 4、编写驱动主类 4.1 在主类中指定我们的分区类是谁 job.setPartitionerClass(MyPartitioner.class); 4.2 设置Reduce的个数 job.setNumReduceTasks(50);
-
实现
参考代码
-
(重点)排序
-
概述
1、MapReduce中只能根据K2进行排序 2、如果想按照某个字段排序,则应该把这个字段包含在K2中
-
注意要点
1、如果在MR中自定义Java类,则MR对该类有以下要求 1) 要求该类必须能够被序列号 : 实现接口 Writable 2) 如果该类作为K2,则要求该类必须指定排序规则,被排序: 实现WritableComparable接口 2、Writable和WritableComparable关系 public interface WritableComparable<T> extends Writable, Comparable<T> {}
-
序列化和反序列化
-
操作
/* 1、如果在MR中自定义Java类,则MR对该类有以下要求 1) 要求该类必须能够被序列号和反序列 : 实现接口 Writable 2) 如果该类对象作为K2,则要求该类必须指定排序规则,被排序: 实现WritableComparable接口 public interface WritableComparable<T> extends Writable, Comparable<T> {} Writable父接口: WritableComparable子接口 */ public class Covidbean implements WritableComparable<Covidbean> { private String state; private String country; private Integer cases; private Integer deaths; public String getState() { return state; } public void setState(String state) { this.state = state; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public Integer getCases() { return cases; } public void setCases(Integer cases) { this.cases = cases; } public Integer getDeaths() { return deaths; } public void setDeaths(Integer deaths) { this.deaths = deaths; } //后边在向文件写对象数据时,需要使用该类的toString方法 @Override public String toString() { return state + "\t" + country + "\t" + cases + "\t"+ deaths; } /* 1、在此需要给当前类设置一个比较器,用来实现两个对象之间的比较,最终用于MR的排序 2、我们只需要指定排序规则,不需要排序 3、compareTo方法只需要返回三个值: 大于0的值 小于0的值 等于0的值 4、比较器默认是升序 */ @Override public int compareTo(Covidbean o) { //规则:按照确诊人数进行降序排序,如果确诊人数相同,则按照死亡人数降序排序 int result = this.cases - o.cases; if(result == 0){ return (this.deaths - o.deaths) * -1; }else{ return result * -1; } } //序列化方法 @Override public void write(DataOutput out) throws IOException { out.writeUTF(state); out.writeUTF(country); out.writeInt(cases); out.writeInt(deaths); } //反序列化方法 //反序列化的字段顺序必须和序列化字段顺序一致 @Override public void readFields(DataInput in) throws IOException { this.state = in.readUTF(); this.country = in.readUTF(); this.cases = in.readInt(); this.deaths = in.readInt(); } }
Combiner(规约)
-
概念
1、规约(Combiner)是MapReduce中的优化手段,将每一个Map的数据进行提前的聚合,减少Map端和Reduce端网络传输的数据量 2、规约可以理解为Reduce的逻辑在每一个Map端先执行一遍 3、Reduce是对所有的Map的数据进行汇总,而规约是对每一个Map的结果进行汇总 4、Combiner只是一种优化手段,不能改变最终的执行结果
-
操作
规约的实现步骤: 1、自定义类继承Reducer类 2、重写reduce方法,在该方法中实现规约 3、在主类中设置规约类 job.setCombinerClass(CustomCombiner.class)
-
代码
(重点)分组
-
概念
1、分组的作用就是去K2进行去重,然后相同K2的V2存入集合 hello 1 hello 1 -----分组--------> hello [1,1,1] ----reduceTask----> hello 3 hello 1 2、MR默认的分组是根据K2来决定的,相同K2的数据会被分到同一组 3、当默认的分组,不满足我们的需求时,我们可以使用自定义分组 4、当我们没有指定分组规则时,系统默认调用K2类中的compareTo方法,如果我们自定义了分组规则,则就按照我们的方式来实现分组
-
分组的操作
-
需求
1、求美国每个州确诊人数最多的县的信息 Top1 select 州,max(cases) from covid group by 州;
-
步骤
1:自定义类继承WritableComparator类 2:编写无参构造方法,该方法需要调用父类的有参构造 3:重写compare方法,在该方法中指定分组的规则 4:在主类中指定自定义分组类 job.setGroupingComparatorClass(GroupingComparator.class);
-
(重点)MapReduce运行过程
- 逻辑切片
-
环形缓冲区
1、本质上是一个字节数组 2、环形缓冲区大小是100M,当数据达到80M时溢出
Reduce端join
-
特点
1、将多张表的数据分别读取,发送到reduce,则reduce端完成join操作 FileSplit fileSplit = (FileSplit) context.getInputSplit(); //获取文件切片 String fileName = fileSplit.getPath().getName(); //获取源文件的名字 2、一般大表join大表,需要使用Reduce端join
Map端Join
-
特点
1、将小表存入分布式缓存中,然后把分布式缓存的小表数据读取到本地每一个MapTask的Map集合 2、将大表通过正常的MapReduce流程进行读取,然后和Map集合中的数据进行join 3、Map端join一般用于小表join大表,而且Map端join没有Reduce
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jbhmoHwy-1664119905535)(MapReduec框架.assets/image-20220925170306027.png)]