hadoop_MapReduce详解

MapReduce秒懂

MapReduce定义

MapReduce是一个分布式运算程序的编程框架

MapReduc优缺点

优点

  1. 易于编程
  2. 良好的扩展性
  3. 高容错性
  4. 适合PB级以上海量数据的离线计算

缺点

  1. 不擅长实时计算
  2. 不擅长流式计算
  3. 不擅长DAG(有向图)计算

MapReduc核心思想

  1. Job(作业) : 一个MapReduce程序称为一个Job,MR程序一般需要分成2个阶段:map阶段和reduce阶段
  2. MRAppMaster:MR任务的主节点,一个Job在运行时,会先启动这个进程,负责Job中执行状态的监控、容错、RM申请资源、提交Task等等
  3. Map是MapReduce程序运行的第一个阶段,MapTask负责是Map阶段程序的计算,在一个MR程序的Map阶段,会启动N个MapTask,每个MapTask是完全并行运行,互不相干
  4. Reduce是MapReduce程序运行的第二个阶段(最后一个阶段),Reduce阶段的目的是将Map阶段,每个MapTask计算后的结果进行合并汇总,数据依赖于上一个阶段的所有MapTask并发实例的输出,ReduceTask也是并行运行,每个ReduceTask最终都会产生一个结果
  5. MapReduce程序只能包含一个Map阶段和一个Reduce阶段,如果用户的业务逻辑非常复杂,那就只能多个MapReduce程序,串行运行

MapReduc工作流程

Map阶段

切片(split)

切片指的是MapReduce框架根据输入数据源的大小和配置参数,将数据源分割成多个较小的数据集合,每个数据集合称为一个切片(Split),每个切片会被分配给一个单独的MapTask进行处理

InputFormat

MR程序必须指定一个输入目录,一个输出目录,InputFormat代表输入目录文件的格式。默认的是普通文件,使用FileInputFormat,如果处理的数据在数据库中,需要使用DBInputFormat

FileInputFormat

用来读取数据,其本身为一个抽象类,继承自 InputFormat 抽象类,针对不同的类型的数据有不同的子类来处理,不同的子类有着不同的切片机制,常见的接口实现类如下:

  • TextInputFormat(默认)

      切片机制:
      	1. 通过计算文件的起始位置、文件的长度以及配置的块大小,简单的按照文件的内容长度进行切片
      	2. 切片大小,默认等于Block大小(blocksize)
      	3. 切片时不考虑数据集整体,而是逐个针对每一个文件单独切片
      	4. 每次切片时,都要判断切完剩下的部分是否大于块的1.1倍,不大于1.1倍就划分为一块切片
    
  • KeyValueTextInputFormat

      按行读取,每一行为一条记录,被分隔符分隔,默认分隔符为'\t'
    
  • NLineInputFormat

      切片机制按照指定的行数N来划分,即输入文件的总行数/N=切片数,不能整除则+1片
    
  • CombineTextInputFormat

      用于小文件过多的场景,它可以将多个小文件从逻辑上规划到一个切片中,这样多个小文件就可以交给一个MapTask处理
      切片机制:
      	包括虚拟存储过程和切片两个部分
      虚拟存储过程:
      	1. 将输入目录下所有文件按照文件名称字典顺序一次读入,记录文件大小,并累加计算所有文件的总长度
      	2. 根据设置的虚拟存储切片最大值,将每个文件划分成一个一个设置的切片值大小的文件
      	3. 当剩余数据大小超过设置的切片值且不大于2倍时,将文件均分成2个虚拟存储块(防止出现太小切片)
      切片过程:
      	1. 判断虚拟存储的文件大小是否大于设置的切片值,大于等于则单独形成一个切片
      	2. 如果不大于则跟下一个虚拟存储文件进行合并,共同形成一个切片
      举例:
      	text1大小2M、text2大小5M、text3大小3M、text4大小6M
      	设置的虚拟存储切片最大值为4M
      	虚拟存储过程:
      		text1:2M < 4M 划分为1块
      		text2:4M < 5M < 2 * 4M 划分为2块,块1:2.5M,块2:2.5M
      		text3:3M < 4M 划分为1块
      		text4:6M < 5M < 2 * 4M 划分为2块,块1:3M,块2:3M
      		最终虚拟存储过程划分的块数为6块,2M、2.5M、2.5M、3M、3M、3M
      	切片过程:
      		没有文件大小是大于4M的,所以俩俩合并共同形成一个切片,最终切片为3块
      		2 + 2.5 = 4.5M
      		2.5 + 3 = 5.5M
      		3 + 3 = 6M
    
  • 自定义InputFormat

FileInputFormat切片机制

  1. 通过计算文件的起始位置、文件的长度以及配置的块大小,简单的按照文件的内容长度进行切片
  2. 切片大小,默认等于Block大小(blocksize)
  3. 切片时不考虑数据集整体,而是逐个针对每一个文件单独切片

FileInputFormat切片流程

  1. 程序先找到你数据存储的目录
  2. 开始遍历处理目录下的每一个文件
  3. 遍历第一个文件,获取文件的大小,计算设置切片的大小(默认是块大小128M),开始切片
  4. 将切片信息写到一个切片规划文件中
  5. 提交切片规划文件到YARN上,YARN的MRAppMaster根据切片规划文件计算开启MapTask个数

读取(RecordReader)

RecordReader负责从输入格式中,读取数据,读取后封装为一组记录(k-v),mapreduce只能处理kv

处理(mapper)

将解析出的key_value交给map()函数处理,并产生一系列新的key_value

收集(collect)

收集线程负责将写出的key-value收集到缓冲区(MapOutPutBuffer)中,每个记录在进入缓冲区时,先调用Partitioner(分区器)为记录计算一个区号

  • 缓冲区默认大小为100M

溢写(spill)

溢写线程会在缓冲区已经收集了80%空间的数据时被唤醒,唤醒后负责将缓冲区收集的数据溢写到磁盘上,生成一个临时文件

溢写流程

  1. 一旦缓冲区满足溢写条件,先对缓冲区的所有数据,进行一次排序,排序方式是先按照分区编号Partition进行排序,然后按照key进行升序排序,排序时,只排索引不移动数据,经过排序后,数据以分区为单位聚集在一起,且同一分区内所有数据按照key有序
  2. 按照分区编号由小到大进行溢写,将每个分区中的数据写入任务工作目录下的临时文件中,溢写多次,生成多个临时文件,如果最后一批数据不满足溢写条件会执行一次flush
  3. 将分区数据的元信息写到内存索引数据结构SpillRecord中,其中每个分区的元信息包括在临时文件中的偏移量、压缩前数据大小和压缩后数据大小

合并(combine)

溢写结束后,MapTask对所有临时文件进行一次合并,以确保最终只会生成一个数据文件。因为后续reduce会读取文件,这样可避免同时读取大量文件产生的开销

合并流程

  1. MapTask以分区为单位进行合并。对于某个分区,它将采用多轮递归合并的方式
  2. 每轮合并10(默认)个文件,并将产生的文件重新加入待合并列表中
  3. 对文件进行排序,重复以上过程,直到最终得到一个大文件,这个文件每个分区中的key-value都是有序的
  4. 最终将数据写入到MapTask磁盘的某个文件中

Reduce阶段

拷贝(copy)

ReduceTask从各个MapTask上远程拷贝数据,每个ReduceTask只负责一个分区,所以只copy不同MapTask上这个分区的数据,针对某一片数据,如果其大小超过一定阈值,则写到磁盘上,否则直接放到内存中

合并(merge)

在远程拷贝数据的同时,ReduceTask启动了两个后台线程对内存和磁盘上的文件进行合并,以防止内存使用过多或磁盘上文件过多

  1. 文件大小超过一定阈值,则放到磁盘上,否则放到内存中
  2. 磁盘上的文件数目达到一定阈值,进行一次合并,生成一个更大的文件
  3. 内存中文件大小或者数目超过一定阈值,进行一次合并后将数据写到磁盘上

排序(sort)

由于数据是从多个MapTask上copy过来的,所以要对所有数据进行一次归并排序,保证在进入reduce之前是排好序的

处理(reducer)

将排好序的数据进行分组,调用reduce()函数处理数据,将计算结果写到文件上

分区概述

分区是在MapTask中通过Partitioner来计算分区号

  1. 总的partitions(分区数),取决于用户设置的reduceTask的数量
  2. partitions>1,默认尝试获取用户设置的分区数,如果用户没有定义,那么会使用HashPartitioner,HashPartitioner根据key的hashcode进行计算,相同的key以及hash值相同的key会分到一个区
  3. partitions<=1,默认初始化一个Partitioner,这个Partitioner计算的所有的区号都为0

排序概述

排序是MapReduce框架中最重要的操作之一,MapTask和ReduceTask均会对数据按照key进行排序,该操作属于Hadoop的默认行为,任何应用程序中的数据均会被排序,而不管逻辑上是否需要。默认排序是按照字典顺序排序,且实现该排序的方法是快速排序

排序分类

  • 部分排序

      MapReduce根据输入记录的键值对数据集排序,最终生成N个结果文件,每个文件内部整体有序
    
  • 辅助排序

     在进入reduce阶段时,通过比较key是否相同,将相同的key分为一组
    
  • 全排序

      对所有的数据进行排序,指生成一个结果文件,这个结果文件整体有序
    
  • 二次排序

      在对key进行比较时,比较的条件为多个
    
相关推荐
Java 第一深情20 分钟前
零基础入门Flink,掌握基本使用方法
大数据·flink·实时计算
MXsoft61828 分钟前
华为服务器(iBMC)硬件监控指标解读
大数据·运维·数据库
PersistJiao1 小时前
Spark 分布式计算中网络传输和序列化的关系(二)
大数据·网络·spark·序列化·分布式计算
九河云1 小时前
如何对AWS进行节省
大数据·云计算·aws
FreeIPCC2 小时前
谈一下开源生态对 AI人工智能大模型的促进作用
大数据·人工智能·机器人·开源
梦幻通灵2 小时前
ES分词环境实战
大数据·elasticsearch·搜索引擎
Elastic 中国社区官方博客2 小时前
Elasticsearch 中的热点以及如何使用 AutoOps 解决它们
大数据·运维·elasticsearch·搜索引擎·全文检索
天冬忘忧3 小时前
Kafka 工作流程解析:从 Broker 工作原理、节点的服役、退役、副本的生成到数据存储与读写优化
大数据·分布式·kafka
sevevty-seven4 小时前
幻读是什么?用什么隔离级别可以防止幻读
大数据·sql
Yz98765 小时前
hive复杂数据类型Array & Map & Struct & 炸裂函数explode
大数据·数据库·数据仓库·hive·hadoop·数据库开发·big data