MapReduce学习笔记一
一、概述
Map-reduce 自己处理业务相关代码+自身的默认代码
优点:
1、易于编程。只关心业务逻辑和实现框架的接口
2、良好拓展行:可以动态增加服务器
3、高容错性:任何一台机器挂掉,可以将任务转移到其他节点
4、适合海量数据计算(TB/PB)几千台服务器共同计算
缺点:
1、不擅长实时计算。 MySQL
2、不擅长流式计算。 Spark steaming flink
3、不擅长DAG有向无环图 spark
编程规范
用户编写的程序分为3步:mapper、reducer和Driver
1.mapper阶段
1、用户自定义的mapper要继承自己的父类
2、mapper的输入数据是键值对的形式(k、v的类型可以自定义)
3、mapper中的业务逻辑写在map()方法中
4、Mapper的输出数据是键值对的形式(k、v的类型可以自定义)
5、map()方法(Map Task进程)对每一个<K,V>调用一次
2.Reducer阶段
1、用户自定义的Reducer要继承自己的父类
2、Reducer的输入数据类型对应的mapper的输出数据类型,也是键值对
3、Reducer的业务逻辑写在reducer()方法中
4、Reduce Task进程对每一组相同k的<K,V>组调用一次reduce()方法
3、Driver阶段
相当于YARN集群的客户端,用于提交我们整个程序到YARN集群,提交的是封装了Map Reduce程序相关运行参数的job对象
mapper——将数据转换成键值对
reducer——对键值对进行处理
Driver
1.配置信息,获取job对象实例
2.指定本程序的jar包所在的本地路径
3.关联Mapper/Reducer业务类
4.指定Mapper输出数据的k v 类型
5.指定最终输出的数据的k v类型
6.指定job的输入原始文件所在目录
7.指定job的输出结果所在目录
8.提交作业
环境配置
1.创建maven,更改默认maven仓库
2.在pom.xml文件中添加依赖
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>3.1.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
</dependencies>
3.在项目的 src/main/resources 目录下,新建一个文件,命名为“log4j.properties”,在 文件中填入
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
(3)创建包名:com.atguigu.mapreduce.wordcount
4.编写程序(注意导入hadoop相关的包)
alt+回车==抛出异常
此时运行的程序相当于本地运行
放到集群内部的话,需要对程序进行打包
对pom.xml添加打包依赖
二、序列化
2.1优点:
结构紧凑:存储空间少
快速:传输速度快
互操作性
2.2自定义bean对象实现接口
1.必须实现Writable接口(alt+回车,快速重写接口)
2.反序列化是,需要反射调用空参构造函数,所以必须有空参构造
public FlowBean() {
super();
}
3.重写序列化方法
@Override
public void write(DataOutput out) throws IOException {
out.writeLong(upFlow);
out.writeLong(downFlow);
out.writeLong(sumFlow);
}
4.重写反序列化方法
@Override
public void readFields(DataInput in) throws IOException {
upFlow = in.readLong();
downFlow = in.readLong();
sumFlow = in.readLong();
}
5.注意反序列化的顺序和序列化的顺序完全一致
6.要想把结果显示在文件中,需要重写toString(),可以用"\t"分开,方便后续处理
7.如果需要将自定义的bean放在key中传输。则还需要实现Comparable接口,因为Map Reduce框中的Shuffle过程要求对key必须能排列.
@Override
public int compareTo(FlowBean o) {
// 倒序排列,从大到小
return this.sumFlow > o.getSumFlow() ? -1 : 1;
}
案例writable
public class FlowMapper extends Mapper<>
#继承并重写Mapper,泛型中前两个参数是输入的KV,后两个是输出的KV<固定的偏移量LongWritable,输入的一行内容Text,输出的k(可以用字符串表示)Text,
三、核心框架原理
3.1 Input Format数据输入
3.1.1切片与MapTask并行度决定机制
数据块:Block是hdfs物理上把数据分成一块一块。数据块是hdfs存储数据单位。
数据切片:数据切片只是在逻辑上对输入进行分片,并不会在磁盘上将其切分成片进行存储。数据切片是Map Reduce程序计算输入数据的单位,一个切片会对应启动一个Map Task。
1.一个job的Map阶段并行度由客户端在提交Job时的切片数决定
2.每一个Split切片分配一个Map Task并行实例处理
3.默认情况下,切片大小=Block Size(块大小)
4.切片时不考虑数据集整体,而是逐个针对每一个文件单独切片
输出路径保证是不存在的
3.1.4 File Input Format
常见的接口实现类包括:TextInputFormat、KeyValueTextInputFormat、NLineInputFormat和自定义InputFormat等
keyvalueInputFormat
上一篇: 排序算法(一) 冒泡排序