mapreducer的shuffle流程

4.3.1 MapTask的整体概述

1. maptask调用FileInputFormat的createRecordReader通过分片数据来读取原始数据    
2. 会调用nextKeyValue方法获取每行数据,然后返回一个(K,V)对,K是offset,V是一行数据
3. 将k-v对交给Map函数进行处理
4. 每对k-v调用一次map(K,V,context)方法,经过处理,使用context.write(k,v)
5. 写出的数据交给收集器OutputCollector.collect()处理
6. 将数据写入环形缓冲区,并记录写入的起始偏移量,终止偏移量,环形缓冲区默认大小100M
7. 默认写到80%的时候要溢写到磁盘,溢写磁盘的过程中数据继续写入剩余20%
8. 溢写磁盘之前要先进行分区然后分区内进行排序
9. 默认的分区规则是hashpatitioner,即key的hash%reduceNum
10. 默认的排序规则是key的字典顺序,使用的是快速排序
11. 溢写会形成多个文件,在maptask读取完一个分片数据后,会将环形缓冲区数据刷写到磁盘
12. 将数据多个溢写文件进行合并,分区内排序(外部排序===》归并排序)

4.4 运行流程之ReduceTask(重点)

1. reduceTask启动后,开始使用线程fetch属于自己分区的map端产生的临时数据。
2. fetch过来的K2,v2,在内存中会进行归并排序。
3. reduceTask会调用分组器将内存中的k2,v2按照不同的k2来分组。
4. 每一组的<k2,list<v2>>调用一次reduce方法,经过处理,使用context.write(k,v)写出去。
5. 写出去的位置由FileOutputFormat的参数决定。

4.5 Shuffle流程(重点)

4.5.2 map端shuffle
1. map函数的输出数据K2,v2进入环形缓冲区,环形缓冲区默认大小100MB,阈值80MB。
2. 当数据存储达到阈值时,会启动一个线程将该数据溢写出去,剩下的20M会继续写入,当20M写满,80M还未溢写完,则maptask出现阻塞。
3. 在溢写前,会先调用分区器按key分区,然后同一分区的数据进行按key排序,排序算法为QuickSort,规则为字典排序。(注意:分区和排序都是对KV对的元数据进行的)
4. 溢写时会产生临时文件,按照分区号从小到大将每一个分区的数据溢写到文件中(注意:写出时是通过排好序的元数据找到原始数据,写出去)5. 在排序后,溢写前,可以调用combiner函数来减少数据的溢写,目的减少磁盘IO.
6. 如果溢写文件数量有多个的话,会进行再次合并,合并成一个最终的临时文件,合并的时候使用的是归并算法。
7. 如果溢写文件数据至少3个,则在合并排序后,会再次调用combiner函数,来减少最终临时文件的大小。如果数量低于3个,则没有必要调用combiner。
8. 为了减少临时文件到reduce端的网络IO,建议将临时文件压缩,再进行传输。

4.5.3 reduce端shuffle
9. 当某一个mapTask结束后,reduceTask会利用线程开始fetch属于自己要处理的分区的数据,线程默认是5个,线程数量是针对于每一个节点来说的,线程通过HTTP协议抓取数据。
10. 如果抓过来的数据量过小,直接在对应的jvm的内存中进行归并排序,输入给reduce函数
11. 如果数据量过大,则会直接拷贝到所在的本地磁盘上,然后将多个文件合并成较大的文件,合并因子是10,合并时采用的算法是归并算法。(细节:最后一次合并一定要满足10这个因子,而且不会溢写成文件,直接输入给reduce).
12. 在归并算法合并时,如果map端的数据是压缩的,那么要在reduceTask的内存中解压缩在合并。
13. reduce处理后将数据存储到HDFS上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值