hadoop之shuffle混洗

本文详细解析了Hadoop MapReduce中的Shuffle过程,包括map端的环形缓冲区、分区、排序、溢写到磁盘以及merge操作。在reduce阶段,描述了数据如何通过HTTP拉取、合并及reduce函数的执行。整个流程确保了数据的分区、排序以及高效传输。
摘要由CSDN通过智能技术生成

补:combiner函数会使map的输出结果更为紧凑
reduce的数量与map无关,与map的分区数量有关
shuffle:将map输出传给reduce的过程
shuffle洗牌 执行流程

InputFormat–>InputSplit
–>map函数(mapper)
–>环形缓冲区
写入环形内存缓冲区

因为频繁的磁盘I/O操作会严重的降低效率,
因此“中间结果”不会立马写入磁盘,而是优先存储到map节点的“环形内存缓冲区”,
并做一些预排序以提高效率,当写入的数据量达到预先设置的阙值后便会执行一次I/O操作
将数据写入到磁盘。每个map任务都会分配一个环形内存缓冲区,
用于存储map任务输出的键值对(默认大小100MB,mapreduce.task.io.sort.mb调整)

       -->partition(分区) 默认hashpartition分区
       -->sort(排序)
          每个分区中对其中的键值对按键进行sort排序,具体是将数据按照partition和key两个关键字进行排序,
          排序结果为缓冲区内的数据按照partition为单位聚集在一起,
          同一个partition内的数据按照key有序
       -->spill to disk(溢写至此磁盘)
          一旦缓冲区内容达到阀值(mapreduce.map.io.sort.spill.percent,默认0.80,或者80%),
          就会会锁定这80%的内存,排序完成后会创建一个溢出写文件(临时文件),
          然后开启一个后台线程把这部分数据以一个临时文件的方式溢出写(spill)到本地磁盘中 
          剩余的20%的内存在此期间可以继续写入map输出的键值对。
          溢出写过程按轮询方式将缓冲区中的内容写到mapreduce.cluster.local.dir属性指定的目录中

80%到本地磁盘,20%到缓冲区
–>merge(合并)
合并merge

当一个map task处理的数据很大,以至于超过缓冲区内存时,就会生成多个spill文件。
此时就需要对同一个map任务产生的多个spill文件进行合并生成最终的一个已分区且已排序的大文件。
配置属性mapreduce.task.io.sort.factor控制着一次最多能合并多少流,默认值是10。

溢出写文件合并完毕Reduce拉取后,Map将删除所有的临时溢出写文件,并告知NodeManager任务已完成,

       -->存储在maptask节点的本地(本地存储)

———————————————————map端的shuffle结束———————————————————————————————

       -->fetch(通过http协议拉取map端的输出结果,按照partition)
          只要其中一个MapTask完成,ReduceTask就开始复制它的输出
          
       -->merge(合并)将来自不同节点的map输出数据,合并成一个大的文件,供reduce使用;
          
         压缩:在写磁盘的时候采用压缩的方式将map的输出结果进行压缩是一个减少网络开销的有效方法
         并减少传给reducer的数据量。默认情况下,输出是不压缩的(将mapreduce.map.output.compress设置为true即可启动)
   
       -->reduce函数(相同的key2调用一次reduce函数)
         Reduce进程启动一些数据copy线程,通过HTTP方式请求MapTask所在的NodeManager以获取输出文件

NodeManager需要为分区文件运行reduce任务。
并且reduce任务需要集群上若干个map任务的map输出作为其特殊的分区文件。
而每个map任务的完成时间可能不同,因此只要有一个任务完成,reduce任务就开始复制其输出。

reduce任务有少量复制线程,因此能够并行取得map输出。默认线程数为5,
但这个默认值可以通过mapreduce.reduce.shuffle.parallelcopies属性进行设置

         当一个reduce任务完成全部的复制和排序后,就会针对已根据键排好序的Key构造对应的
         Value迭代器。这时就要用到分组,默认的根据键分组,
         自定义的可是使用 job.setGroupingComparatorClass()方法设置分组函数类。
         对于默认分组来说,只要这个比较器比较的两个Key相同,它们就属于同一组,它们的 Value就会放在一个Value迭代器,
         而这个迭代器的Key使用属于同一个组的所有Key的第一个Key。

在reduce阶段,reduce()方法的输入是所有的Key和它的Value迭代器。

       -->output输出 
         此阶段的输出直接写到输出文件系统,一般为HDFS。如果采用HDFS,
         由于NodeManager也运行数据节点,所以第一个块副本将被写到本地磁盘

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
map->环形缓冲区->分区->整理->写到本地-合并->reduce读取
上图有4个map,一个reduce用来计算他们的1个分区
在这里插入图片描述
reducer如何知道哪台机器要获得reducer输出呢?
map任务成功完成后,它们会使用心跳机制通知它们的application master。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值