Hadoop-MapReduce初学入门笔记

0 MR简介

MapReduce用于处理海量数据计算,由谷歌论文而来,从论文角度来讲是一种思想,从技术角度来讲。是一种计算框架

1 MR代码规范

 

 1.1 Mapper类

主要设计业务逻辑要什么输出

1.用户定义的Mapper类要继承父类

2.Mapper业务逻辑写在map()方法

3.Mapper输入数据是泛型KV对的形式,输出也是

        Key 是偏移量,value 是值(内容)

4.Map()方法对每个<K,V>调用一次

        在WordCount中一个<K,V>代表一行,即每行调用一次Map()方法

1.2 Reducer类

前两点和Mapper通用:要继承父类、重写reduce方法

1.输入数据类型对应Mapper输出类型

2.对每一组相同k的<k,v>组调用一次reduce()方法

        有几个k就reduce几次

reduce()方法 参数如下:

<key,Iterable<序列化类型> Values (Iterable是集合,因为可能需要累加等操作),outK自定义,outV自定义 >

1.3 Driver类

概念:

类似一种八股文的写法:

2 MR序列化

MR 序列化类型都是对象!

用自己的序列化类型原因是如下,紧凑、快速、互操作性高

序列化的作用:主要用于不同服务器传输(知识点可看CG笔记)

-----------------------------------------------------------------------------------------

3 MR框架原理

3.1 并行度(关系到分区)

MapTask数量:切片数量决定

可通过公式修改切片大小,本地32m。

还有读取方式不同比如TextInputFormat、NLineInputFormat也会影响切片的数量

ReduceTask数量:非自定义分区情况下,ReduceTask影响分区数量
分区Partition

默认分区HashParitioner,按照Key值的hash值%NumReduceTask个数

drive:job.setNumReduceTask(x); 

ReduceTasks可选:0(无Reduce)、1(不分区)、n(要求等于自定义分区数)

自定义时分区,若小于分区数则报错,大于分区数则多出空输出文件

Q:先分区还是先判断ReduceTasks?

A:先判断ReduceNum,不大于1则不执行分区。

Map
切片FileInputFormat、提交Job、Yarn打开MapTask、调用输入组件(TextInputFormat)、调用Map()方法

Mapper Shuffle

Partition分区、OutPutCollector写入环形缓冲区、溢写(之前进行快排Sort、可选合并Combine)、合并溢写文件Merge(归并排序)

Reduce Shuffle

(Copy)拉取相应分区文件 -> (Sort)Merge归并排序 -> (Reduce)分组(Group) 

Reduce

集合聚合

Read -> Map->

Mapper Shuffle分区Partition -> OutPutCollector环形缓冲区  -> 溢写(溢写之前 快速排序Sort,可选合并Combine) -> 合并Merge归并排序 -> Reduce Shuffle(Copy)拉取相应分区文件 -> (Sort)Merge归并排序 -> (Reduce)分组(Group) 

-> Reduce

环形缓冲区:默认100m,80%后溢写。一边存索引,一边存取真实的kv值。

Spill溢写:80%溢写,不100%的原因是因为溢写完成才空余RAM,这样得Map输出受限

·溢写完成后会产生两个文件,一个out文件,一个index文件,用于Reduce判断拉取数据。

MapperShuffler排序:快排,排列对象是KV对的索引,按字典顺序

Combine合并:分区内提前Reduce,是一种优化手段,继承Reduce。慎重使用,如求中位数不一定一样了

Merge归并排序:对已经有序的序列进行排序最优。

·第一个是合并溢写的文件,第二个是合并不同分区拉过来的文件

MAP压缩:在Merge之后,落盘前

Group分组:因为执行完毕后Key是排序的,一次读一组,values聚合成集合

·有一个辅助方法也可以实现排序(非系统默认实现的)

4 数据IO

4.1 FileInputFormat 切片机制

切片是MAP的最小计算单元,一般等同于块大小。(Local模式一般为32m)

4.2 数据输入

FileInputFormat(文件输入)后,可以选择如何输入进Map()方法,继承关系如下:

默认输入组件TextInputFormat,调用里面的RecorderReader读取数据

处理小文件:CombineTextInputFormat,把多个文件合并到一起统一切片

4.3 FileInputFormat机制源码解析

 4.4 OutputFormat

5 MR排序

Key必须支持排序,MR执行期间自动排序,执行完毕后,key都是有序的。

排序种类
1)部分排序
每个分区的key是有序的,但分区和分区之间是无序的
2)全排序
最终输出只有一个文件,不仅每个分区的key是有序的,而且分区和分区也是有序的
        ·生产环境下慎用!文件量太大,聚合在一个reduce顶不住

3)二次排序

在自定义排序过程中,如果compareTo中判断条件为两个则为二次排序

        ·比如总流量相同,再按上行流量再排序


两种情况

排序代码在序列化类型中修改,因为排序讨论对象为Key
1.原生的序列化类型,已经实现Comparable接口,在源代码中重写comparaTo
方法提供默认排序规则
2.自定义序列化类型,若作为Key,定义时必须implements Comparable接口,重写comparaTo方法,之后提供默认排序规则。若需要自定义排序规则则按业务逻辑重写。

默认顺序
数字从小到大排序

字符串按字典顺序排序


6 Join

1 Reduce Join

标记不同来源的文件,将相同字段作为key进行多表连接。

自定义序列化Bean:

需要包含多表的所有字段(无需重复)+ flag文件来源。

Map:

1、Steup()初始化获取输入文件

        FileSplit split = (FileSplit) context.getInputSplit();

        fileName = split.getPath().getName();

2、不同文件分别处理(切割)

3、封装Bean对象输出。如pd表仅两个字段,其余other表才有的字段可封装nullWriteable

此时Other和pd每行都有各自的Bean对象,进入Reduce后聚合成想要的数据

Reduce:

1、创建两个集合

        ·现在有3个集合,传来的Bean(赋值用),新建的2个

2、遍历传来的Bean,判断来源是哪个表,赋值给两个新定义的集合

3、将想要整合的字段,从另一个集合取出get,封装到另一个集合

4、输出封装的集合,由于所有字段都在,所以V为NullWriteable

缺点:这种方式中,合并的操作是在Reduce阶段完成,Reduce端的处理压力太大,Map节点的运算负载则很低,资源利用率不高,且在Reduce阶段极易产生数据倾斜。

2 Map Join

Map Join适用于一张表非常小,一张表十分大的场景。

Map端缓存多张表,提前处理业务逻辑,这样增加Map端业务,减少Reduce端数据的压力,尽可能的减少数据倾斜。

Driver

        // 加载缓存数据
        job.addCacheFile(new URI("file:///D:/input/tablecache/pd.txt"));

        // Map端Join的逻辑不需要Reduce阶段,设置reduceTask数量为0
        job.setNumReduceTasks(0);

Map

1、Setup获取缓存的文件

2、开流从中读数据并赋值给集合

3、从原表取出(切割)需要的字段,并从刚才赋值的集合取出需要的字段,一起连接封装

outK.set(words[0] + "\t" + pname + "\t" + words[2]);
//放弃pid,改为缓存中取出的name

7 ETL 数据清洗

比如清洗掉不符合手机号规则的手机,过短的日志文件。

7.1 数据清洗过程往往只需要运行Map,不需要写Reduce类。

        ·一般在Map中写一个校验规则,输出即可

        ·筛选一般输入<K,V>后MAP仅输出<V,NullWriteable>

7.2 各类正则校验规则(可百度)能符合大多数企业下的应用场景


8 压缩

8.1 压缩概念

Hadoop处理大量数据时,可通过CPU分担一定的IO压力,可以在计算和空间中寻求一个性价比最高的状态。

1、计算密集型程序:减少压缩机制

2、IO密集型程序:多使用压缩

8.2 Hadoop的压缩算法

Snappy要求较高:Liunx7+、Hadoop3.0+、IDEA需要配置

8.3 使用

Driver:
        // 设置map端输出压缩开启
		configuration.setBoolean("mapreduce.map.output.compress", true);

        // 设置map端输出压缩方式
		configuration.setClass("mapreduce.map.output.compress.codec",
BZip2Codec.class,CompressionCodec.class);

//    	configuration.setClass("mapreduce.map.output.compress.codec",
GzipCodec.class,CompressionCodec.class);
//	    configuration.setClass("mapreduce.map.output.compress.codec",
DefaultCodec.class,CompressionCodec.class);

/*************************************************************************/

        // 设置reduce端输出压缩开启
		FileOutputFormat.setCompressOutput(job, true);

        // 设置压缩的方式
	    FileOutputFormat.setOutputCompressorClass(job, BZip2Codec.class); 
//      FileOutputFormat.setOutputCompressorClass(job, GzipCodec.class); 
//	    FileOutputFormat.setOutputCompressorClass(job, DefaultCodec.class); 

9 总结

完成一个MR就是组装、设计的过程

自定义相应的 序列化、分区、排序,写相应Map、Reduce。

进阶还可以自定义IO

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值