文章目录
MapTask运行机制(了解)
- Read阶段:MapTask通过用户编写的RecordReader,从输入InputSplit中解析出一个个key/value。
- Map阶段:该节点主要是将解析出的key/value交给用户编写map()函数处理,并产生一系列新的key/value。
- Collect收集阶段:在用户编写map()函数中,当数据处理完成后,一般会调用OutputCollector.collect()输出结果。在该函数内部,它会将生成的key/value分区(调用Partitioner),并写入一个环形内存缓冲区中。
- Spill阶段:即“溢写”,当环形缓冲区满后,MapReduce会将数据写到本地磁盘上,生成一个临时文件。需要注意的是,将数据写入本地磁盘之前,先要对数据进行一次本地排序,并在必要时对数据进行合并、压缩等操作
- Combine阶段:当所有数据处理完成后,MapTask对所有临时文件进行一次合并,以确保最终只会生成一个数据文件。
- 当所有数据处理完后,MapTask会将所有临时文件合并成一个大文件,并保存到文件output/file.out中,同时生成相应的索引文件output/file.out.index。
MapTask的并行度决定机制
- MapTask的并行度决定Map阶段的任务处理并发度,从而影响到整个Job的处理速度。
- MapTask的并行度不是是越多越好,如果一个文件仅仅比128M大一点点也被当成一个split来对待,而不是多个split,如果一个是128M,另一个是1M;对于1M的切片的Maptask来说,太浪费资源。
- Block是HDFS在物理上把数据分成一块一块的。
- 数据切片只是在逻辑上对输入进行分片,并不会在磁盘上将其切分成片进行存储。
数据切片与MapTask并行度决定机制
- 一个job的Map阶段并行度由客户端在提交Job时的切片数决定
- 每一个splits切篇分配一个MapTask并行实例处理,默认情况下,切片大小等于BlockSize
- 数据切片时不考虑数据集的整体性,而是逐个针对每一个文件单独切片。
FileInputFormat切片机制
- 简单的按照文件的内容长度进行切片。
- 切片大小,默认等于Block大小。
- 切片时不考虑数据集整体,而是逐个针对每个文件单独切片。
CombineTextInputFormat切片机制
- MapReduce框架默认的TextInputFormat切片机制是对任务按文件规划切片,不管文件多小,都会是一个单独的切片,都会交给一个MapTask,如果有大量小文件,就会产生大量的MapTask,处理效率极其低下。
ReduceTask 工作机制(了解)
- Reduce大致分为copy、Merge,sort、reduce三个阶段。
- Copy阶段:ReduceTask从各个MapTask上远程拷贝一片数据,并针对某一片数据,如果其大小超过一定阈值,则写到磁盘上,否则直接放到内存中。
- Merge阶段:在远程拷贝数据的同时,ReduceTask启动了两个后台线程分别为inMemoryMerger和onDiskMerger,对内存和磁盘上的文件进行合并,以防止内存使用过多或磁盘上文件过多。
- Sort阶段:按照MapReduce语义,用户编写reduce()函数输入数据是按key进行聚集的一组数据。为了将key相同的数据聚在一起,Hadoop采用了基于排序的策略。由于各个MapTask已经实现对自己的处理结果进行了局部排序,因此,ReduceTask只需对所有数据进行一次归并排序即可。
- Reduce阶段:reduce()函数将计算结果写到HDFS上。
ReduceTask并行度
-
ReduceTask的并行度同样影响整个Job的执行并发度和执行效率,但与MapTask的并发数由切片数决定不同,ReduceTask数量的决定是可以直接手动设置:
// 默认值是1,手动设置为4 job.setNumReduceTasks(4)
-
ReduceTask=0,表示没有Reduce阶段,输出文件数和MapTask数量保持一致;
-
ReduceTask数量不设置默认就是一个,输出文件数量为1个;
-
如果数据分布不均匀,可能在Reduce阶段产生倾斜;
Shuffle机制(了解)
- map阶段处理的数据如何传递给reduce阶段,是MapReduce框架中最关键的一个流程,这个流程就叫shuffle。
- shuffle: 洗牌、发牌——(核心机制:数据分区,排序,分组,combine,合并等过程)
MapReduce的分区与reduceTask的数量
- 在MapReduce中,通过我们指定分区,会将同一个分区的数据发送到同一个reduce当中进行处理(默认是key相同去往同个分区),例如我们为了数据的统计,我们可以把一批类似的数据发送到同一个reduce当中去,在同一个reduce当中统计相同类型的数据,
- 只需要保证相同key的数据分发到同个分区即可,MR程序shuffle机制默认就是这种规则!
MapReduce中的Combiner
- Combiner是MR程序中Mapper和Reducer之外的一种组件。
- Combiner组件的父类就是Reducer,Combiner和reducer的区别在于运行的位置
- Combiner是在每一个maptask所在的节点运行
- Combiner的意义就是对每一个maptask的输出进行局部汇总,以减小网络传输量。
- Combiner能够应用的前提是不能影响最终的业务逻辑,此外,Combiner的输出kv应该跟reducer的输入kv类型要对应起来。
MapReduce中的排序
- MapTask和ReduceTask均会对数据按照key进行排序。该操作属于Hadoop的默认行为
- 任何应用程序中的数据均会被排序,而不管逻辑.上是否需要。默认排序是按照字典顺序排序,且实现该排序的方法是快速排序。
- MapTask会将处理的结果暂时放到环形缓冲区中,当环形缓冲区使用率达到一定阈值后,再对缓冲区中的数据进行一次快速排序,并将这些有序数据溢写到磁盘上,溢写完毕后,它会对磁盘上所有文件进行归并排序。
- ReduceTask 当所有数据拷贝完毕后,ReduceTask统-对内存和磁盘上的所有数据进行一次归并排序。
- 部分排序:MapReduce根据输入记录的键对数据集排序。保证输出的每个文件内部有序。
- 全排序:最终输出结果只有一个文件,且文件内部有序。实现方式是只设置一个ReduceTask。但该方法在处理大型文件时效率极低,因为一台机器处理所有文件,完全丧失了MapReduce所提供的并行架构
- 辅助排序: ( GroupingComparator分组),在Reduce端对key进行分组。应用于:在接收的key为bean对象时,想让一个或几个字段相同(全部字段比较不相同)的key进入到同一个reduce方法时,可以采用分组排序。
- 二次排序:在自定义排序过程中,如果compareTo中的判断条件为两个即为二次排序。
数据倾斜解决方案
- 数据倾斜就是大量的相同key被partition分配到一个分区里
- 数据倾斜表现为绝大多数task执行得都非常快,但个别task执行的极慢。甚至失败!
- 数据倾斜解决方案对key增加随机数。
MapReduce读取和输出数据
InputFormat
- 运行MapReduce程序时,输入的文件格式包括:基于行的日志文件、二进制格式文件、数据库表等
- 针对不同的数据类型,MapReduce框架用来InputFormat读取数据
- InputFormat常见子类包括:
- TextInputFormat (普通文本文件,MR框架默认的读取实现类型)
- KeyValueTextInputFormat(读取一行文本数据按照指定分隔符,把数据封装为kv类型)
- NLineInputF ormat(读取数据按照行数进行划分分片)
- CombineTextInputFormat(合并小文件,避免启动过多MapTask任务)
- 自定义InputFormat
- MR框架默认的TextInputFormat切片机制按文件划分切片,文件无论多小,都是单独一个切片然后由一个MapTask处理,如果有大量小文件,就对应的会生成并启动大量的 MapTask,而每个MapTask处理的数据量很小大量时间浪费在初始化资源启动收回等阶段,这种方式导致资源利用率不高。
- CombineTextInputFormat用于小文件过多的场景,它可以将多个小文件从逻辑上划分成一个切片,这样多个小文件就可以交给一个MapTask处理,提高资源利用率。
OutputFormat
- OutputFormat:是MapReduce输出数据的基类,所有MapReduce的数据输出都实现了OutputFormat抽象类。
- 文本输出TextOutputFormat子类
- OutputFormat默认的输出格式是TextOutputFormat,它把每条记录写为文本行。它的键和值可以是任意类型,因为TextOutputFormat调用toString()方 法把它们转换为字符串。
- SequenceFileOutputFormat子类
3. OutputFormat将SequenceFileOutputFormat输出作为后续MapReduce任务的输入,这是一种好的输出格式,因为它的格式紧凑,很容易被压缩。
Reduce Join工作原理
- Map端的主要工作:为来自不同表或文件的key/value对,打标签以区别不同来源的记录,然后使用连接字段作为key,其余部分和新加的标志作为value,最后进行输出。
- Reduce端的主要工作:在Reduce 端以连接字段作为key的分组已经完成,只需要在每个分组中将那些来源于不同文件的记录(在Map阶段标记过了)分开,最后进行合并就好了。
Reduce Join的缺点及解决方案
- Reduce Join的合并操作做Reduce 阶段完成,Reduce阶段的处理压力太大,Map节点运算压力小,资源利用率不高,且在Reduce阶段极易产生数据倾斜
- 解决方案:Map端实现数据合并