MapReduce
一、MapReduce概述
- MapReduce是一个分布式运算程序的编程框架,是基于Hadoop的数据分析计算的核心框架。
MapReduce处理过程为两个阶段:Map和Reduce。
- Map负责把一个任务分解成多个任务;
- Reduce负责把分解后多任务处理的结果汇总。
- MapReduce优点
- MapReduce易于编程
它简单的实现一些接口,就可以完成一个分布式程序,这个分布式程序可以分布到大量廉价的PC机器上运行。也就是说你写一个分布式程序,跟写一个简单的串行程序是一模一样的。就是因为这个特点使得MapReduce编程变得非常流行。 - 良好的扩展性
当你的计算资源不能得到满足的时候,你可以通过简单的增加机器来扩展它的计算能力。 - 高容错性
-MapReduce设计的初衷就是使程序能够部署在廉价的PC机器上,这就要求它具有很高的容错性。比如其中一台机器挂了,它可以把上面的计算任务转移到另外一个节点上运行,不至于这个任务运行失败,而且这个过程不需要人工参与,而完全是由Hadoop内部完成的。 - 适合PB级以上海量数据的离线处理
可以实现上千台服务器集群开发工作,提供数据处理能力。
- MapReduce缺点
- 不擅长实时计算
- 不擅长流式计算
流式计算的输入数据是动态的,而MapReduce的输入数据是静态的,不能动态变化。这是因为MapReduce自身的设计特点决定了数据源必须是静态的。 - 不擅长DAG(有向图)计算
多个应用程序存在依赖关系,后一个应用程序的输入为前一个的输出。在这种情况下,MapReduce并不是不能做,而是使用后,每个MapReduce作业的输出结果都会写入到磁盘,会造成大量的磁盘IO,导致性能非常的低下。
MapReduce核心编程思想
1)分布式的运算程序往往需要分成至少2个阶段。
2)第一个阶段的MapTask并发实例,完全并行运行,互不相干。
3)第二个阶段的ReduceTask并发实例互不相干,但是他们的数据依赖于上一个阶段的所有MapTask并发实例的输出。
4)MapReduce编程模型只能包含一个Map阶段和一个Reduce阶段,如果用户的业务逻辑非常复杂,那就只能多个MapReduce程序,串行运行。
总结:分析WordCount数据流走向深入理解MapReduce核心思想。- 常用序列化类型
- MapTask的并行度决定机制
数据块:Block是HDFS物理上把数据分成一块一块。
数据切分:数据切分只是在逻辑上对输入进行分片,并不会在磁盘上将其切分成片进行存储。(只是在切分时默认按照块大小来切分) - FileInputFormat切片源码解析
1) 程序先找到你数据存储的目录。
2)开始遍历处理(规划切片)目录下的每一个文件
3)遍历第一个文件ss.txt
a) 获取文件大小fs.sizeOf(ss.txt)
b) 计算切片大小
computeSplitSize(Math.max(minSize.Math.min(maxSize,blocksize)))=blocksize=128M
c) 默认情况下,切片大小=blocksize
d)开始切,形成第一个切片:ss.txt–0:128M 第二个切片ss.txt–128:256M 第三个切片ss.txt–256M:300M(每次切片时,都要判断切完剩下的部分是否大于块的1.1倍,不大于1.1倍就划分一块切片)
e)将切片信息写到一个切片规划文件中
f)整个切片的核心过程在getSplit()方法中完成
g) InputSplit只记录了切片的元数据信息,比如起始位置、长度以及所在的节点列表等。
4)提交切片规划文件到YARN上,YARN上的MrAppMaster就可以根据切片规划文件计算开启MapTask个数。 - FileInputFormat切片机制
1)简单地按照文件的内容长度进行切片
2)切片大小,默认等于Block大小
3)切片时不考虑数据集整体,而是逐个针对每一个文件单独切片
针对不同的文件类型FileInputFormat有不同的文件接口。 - CombineTextInputFormat切片机制
CombineTextInputFormat用于小文件过多的场景,它可以将多个小文件从逻辑上规划到一个切片中,这样,多个小文件就可以交给一个MapTask处理。 - NLineInputFormat
NLineInputFormat每个map进程处理的InputSplit不再按Block块去划分,而是按NLineInputFormat指定的行数N来划分。 - NLineInputFormat
可指定分片数。
二、自定义inputformat案例
- 需求
- 自定义一个类继承FileInputFormat
1)重写isSplitable()方法,返回false不可分割
2)重写createRecordReader(),创建自定义的RecordReader对象,并初始化- 改写RecordReader,实现一次读取一个完整文件封装为KV
1)采用IO流一次读取一个文件输出到value中,因为设置了不可切片,最终把所有文件都封装到了value中
2)获取文件路径信息+名称,并设置key- 设置Driver
1)设置输入的inputFormat
2)设置输出的outputFormat
二、MapReduce详细工作流程
- MapReduce详细工作流程(一)
- 待处理文本 xx.txt
- 提交前要获取参数信息,形成一个任务分配的规划
- 提交信息 job(看是yarn 还是本地)
- APPmaster接收请求,根据切片来计算出开多少个MapTask
- 按照默认切片方式128M为一块,默认按照TextInputFormat读数据
- 将kv内容交给Mapper(逻辑运算内容) 业务逻辑
- 将数据写到环形缓冲区,包含元数据信息和真实输入的kv,元数据中包含索引、分区信息、key起始、value起始等信息。
- 分区、排序。
- 将缓冲区文件,溢写到文件,并分区且区内有序。
- Merge 归并,将溢写出的文件合并并排序
- 合并
- MapReduce详细工作流程(二)
- reduce根据当前分区的个数(MapTask数目)开启reduce Task进程
- 下载到ReduceTask本地磁盘,对每个分区做合并并进行归并排序
14.使用reduce方法 读文件数据- 分组
- 默认TextOutputFormat
三、Shuffle机制
- Shuffle机制
Map方法之后,Reduce方法之前的数据处理过程称之为Shuffle。 - Map方法将 kv数据写入环形缓冲区,默认100M 当达到80%时会向磁盘溢写,(可选流程)将溢写到磁盘的分区进行合并排序
- reduce 拷贝maptask处理的分区数据放入内存,如果内存不够写入磁盘,对每一个map来的数据归并排序,按照相同的key执行reduce方法。
四、Partition分区
要求将统计结果按照条件输出到不同文件(分区)中去。
分区总结:
五、排序
指定排序规则。
- 概述
排序是MapReduce框架中最重要的操作之一。
MapTask和ReduceTask均会对数据按照key进行排序。该操作属于Hadoop的默认行为。任何应用程序中的数据均会被排序,而不管逻辑上是否需要。
默认排序是按照字典顺序排序,且实现该排序的方法是快速排序。
对应MapTask,它会将处理的结果暂时放到环形缓冲区中,当环形缓冲区使用率达到一定阈值后,再对缓冲区中的数据进行一次快速排序,将这些有序数据溢写到磁盘上,而当数据处理完毕后,它会对磁盘上所有文件进行归并排序。
对于ReduceTask,它会从每个MapTask上远程拷贝相应的数据文件,如果文件大小超过一定阈值,则溢写磁盘上,否则存储在内存中。如果磁盘上文件数目达到一定阈值,则进行一次归并排序以上传一个更大文件;如果内存中文件大小或者数目超过一定阈值,则进行一次合并后将数据溢写到磁盘上。当所有数据拷贝完毕后,ReduceTask统一对内存和磁盘上的所有数据进行一次归并排序。
2. 排序分类
1)部分排序
MapReduce根据输入记录的键对数据集排序。保证输出的每个文件内部有序。
2)全排序
最终输出结果只有一个文件,且文件内部有序。实现方式是只设置一个ReduceTask。但该方法在处理大型文件时效率极低,因为一台机器处理所有文件,完全丧失了MapReduce所提供的并行架构。
3)辅助排序
在reduce端对key进行分组。应用于:在接收的key为bean对象时,想让一个或几个字段相同(全部字段比较不相同)的key进入到同一个reduce方法时,可以采用分组排序。
4)二次排序
自定义排序,如果compareTo中的判断条件为两个即为二次排序。
Combiner合并
- Combiner是MR程序中Mapper和Reducer之外的一种组件。
2)Combiner组件的父类就是Reducer
3)Combiner和Reducer的区别在与运行的位置;Combiner是在每一个MapTask所在的节点运行;Reducer是接收全局所有Mapper的输出结果
4)Combiner的意义就是对每一个MapTask的输出进行局部汇总,以减小网络传输量。
5)Combiner能够应用的前提是不能影响最终的业务逻辑,而且,Combiner的输出kv应该跟Reducer的输入kv类型要对应起来。
OutputFormat接口实现类
OutputFormat是MapReduce输出的基类,所有实现MapReduce输出都实现了OutputFormat接口。
常见的OutputFormat实现类:
- 文本输出TextOutputFormat
默认的输出格式是TextOutputFormat,它把每条记录写为文本行。它的键和值可以是任意类型,因为TextOutputFormat调用toString()方法把它们转换为字符串。 - SequenceFileOutputFormat
将SequenceFileOutputFormat输出作为后续MapReduce任务的输入,这便是一种好的输出格式,因为它的格式紧凑,很容易被压缩。(将小文件合并,节省namenode存储空间)。 - 自定义OutputFormat
根据用户需求,自定义实现输出。
自定义OutputFormat 使用场景及步骤
1.使用场景
为了实现控制最终文件的输出路径和输出格式,可以自定义OutputFormat。
2. 自定义OutputFormat步骤
1)自定义一个类继承FileOutputFormat
2)改写RecordWriter,具体改写输出数据的方法write()。
Join多种应用
- Reduce Join工作原理
map端的主要作用:为来自不同的表或文件的key/value对,打标签以区别不同的来源的记录。然后用连接字段作为key,其余部分和新加的标志作为value,最后进行输出。
reduce端的主要作用:在reduce端以连接字段作为key的分组已经完成,我们只需要在每一个分组当中将那些来源不同的文件的记录(在Map阶段已经打标志)分开,最后进行合并就ok了。 - 案例
4.1 Map Join分析
- 使用场景
Map Join 适用于一张表十分小、一张表十分大的场景(数据倾斜)。 - 优点
reduce端处理过多的表,非常容易导致数据倾斜。于是,在Map端缓存多张表,提前处理业务逻辑,这样增加Map端业务,减少reduce端数据的压力,尽可能的减少数据倾斜。 - 具体办法:采用DistributedCache(分布式缓存)
1)在Mapper的setup阶段,将文件读取到缓存集合中
2)在驱动函数中加载缓存
(也就是将小文件写入缓存中,这样reduce阶段直接从缓存读,不需要重新再磁盘读一遍了)
job.addCacheFile(new URI(“”));
Map端表合并案例分析:
计数器
hadoop为每个作业维护若干内置计数器,以描述多项指标。例如,某些计数器记录已处理的字节数和记录数,使用户可监控已处理的输入数据量和已产生的输出数据量。
- 计数器API
1)采用枚举的方式统计技术
2)采用计数器组、计数器名称的方式统计
3)计数结果在程序运行后的控制台上查看。
数据清洗(ETL)
ETL:萃取、转置、加载。
在运行核心业务MapReduce程序之前,往往要先对数据进行清洗,清理掉不符合用户要求的数据。清洗的过程往往只需进行Mapper程序,不需要运行Reduce程序。
(清洗的量大概每1万条数据有两条需要处理数据)
在map阶段对输入的数据根据规则进行过滤清洗
压缩
1. 压缩概念
压缩技术能够有效减少底层存储系统(HDFS)读写字节数。压缩提高了网络带宽和磁盘空间的效率。在运行MR程序时,I/O操作、网络数据传输、shuffle和merge要花大量的时间,尤其是数据规模很大和工作负载密集的情况下,因此,使用数据压缩显得非常重要。
鉴于磁盘I/O和网络带宽是hadoop的宝贵资源,数据压缩对于节省资源、最小化磁盘I/O和网络传输非常有帮助。可以在任意MapReduce阶段启用压缩。不过,尽管压缩与解压操作的CPU开销不高,其性能的提升和资源的节省并非没有代价。(虽然减少了磁盘IO,但是同时也增加了CPU运算负担)。
压缩策略和原则:压缩是提高Hadoop运行效率的一种优化策略。
1)运算密集型的job,少用压缩(也就是经常用到的数据)
2)IO密集型的job,多用压缩(使用次数少的文件)
2. MR支持的压缩编码
不同的压缩文件对应的解析方法:
Gzip压缩:
- 优点: 压缩率比较高,而且压缩/解压速度比较快;hadoop本身支持,在应用中处理Gzip格式的文件就和直接出来文本一样;大部分Linux系统都自带Gzip命令,使用方便。
- 缺点:不支持Split(那么map之前不支持)
- 应用场景:当每个文件压缩之后在130M以内的(一个块大小内),都可以考虑用Gzip压缩格式。例如说一天或者一个小时的日志压缩成Gzip文件。
Bzip2 压缩
- 优点:支持Split;具有很高的压缩率,比Gzip压缩率高;hadoop本身自带,使用方便
- 缺点:压缩/解压速度慢
- 应用场景:适合对速度要求不高,但需要较高的压缩率的时候;或者输出之后的数据比较大,处理之后的数据需要压缩存档减少磁盘空间并且以后数据用得比较少的情况;或者对单个很大的文本文件想压缩减少存储空间,同时又需要支持Split,而且兼容之前的应用程序的情况。
Lzo压缩
- 优点:压缩/解压速度也比较快,合理的压缩率;支持Split,是hadoop中最流行的压缩格式;可以在linux系统下安装Lzop命令,使用方便。
- 缺点:压缩率比Gzip低;hadoop本身不支持,需要安装;在应用中对Lzo格式的文件需要做一些特殊处理(为了支持Split需要建索引,还需要指定Input/Forma为Lzo格式)
- 应用场景:一个很大的文本文件,在压缩之后还大于200M以上可以考虑,而且单个文件越大,Lzo优点越明显(切片)。
Snappy压缩
- 优点:高速压缩速度和合理的压缩率。
- 缺点:不支持Split;压缩率比Gzip要低;hadoop本身不支持,需要安装。
- 应用场景:当MapReduce作业的map输出的数据比较大的时候,作为map到reduce的中间数据的压缩格式;或者作为一个MapReduce作业的输出和另外一个MapReduce作业的输入。
MapReduce数据压缩