MapReduce工作的详细流程
最近想整理一下Hadoop阶段的知识点 发现MapReduce的运行流程模模糊糊的 网上查的也都写的不全 打算自己整理一下 方便以后看
将写好的MapReduce程序打包 放到集群上 提交任务之后,jobtracker首先会检查输出路径是否存在和输入文件是否存在 不存在会报错
这里解释一下jobtracker 其实就是namenode 只是相对于MapReduce而言
检查无误之后 读取数据 默认是textinputformat对象 可以选择其他读取方式 该对象对输入文件进行切片 默认是128m切一片,切片不是真的切,只是记录切得位置,然后recordread方法会将切好的数据解析
解析成一行一行的 封装成kv v就是每行数据 k是偏移量 这里的偏移量没有什么用
在这里我有个误区 之前我一直以为128m就是一片,但我看了源码 发现之后大于128m的1.1倍才会切一片,而且为了数据完整 会切到下一片的第一行 。假如文件130m 切两片就会启动两个maptask
启动maptask所耗费的资源时间很大 就为了处理2m的数据 不划算
切成几片就会启动几个maptask,封装好的kv会进入到程序员写的map方法中 形成新的kv对
通过context.write()方法将生成的kv写入到磁盘上 然后reduce从磁盘上拉取结果 这一过程就是shuffle 接下来开始详细讲述
collector的write方法会将数据打入环形缓冲区 在这之前 会给该kv对分配一个分区号 分区数就是reducetask的数量 默认分区方法是k的哈希值对reduce数量的取模
进入环形缓冲区 环形缓冲区分为两部分 一部分写数据 一部分写索引 索引其实就是key的其实位置 v的起始位置 分区号和V的长度
环形缓冲区是一块内存 默认100m 当写到80m的时候开始产生溢写 阈值时0.8 可以设置 如果设置了combiner 会调用combinerAndspill combiner预聚合 可以有效的提高效率
但是不能随便使用 有可能会影响结果 比如求平均数 如果没设置combiner 会调用sortAndspill 在溢写之前进行快排 对分区号和key升序排序 移动的只是索引数据 排序完毕之后
就形成了以分区聚集在一起 并且分区内key有序 之后开始进行溢写 如果输入文件很大 会产生多次溢写 每次溢写都会写入到一个新的文件中 同时索引也会写到内存中 如果内存没地方 会写到磁盘上
spill12.out和spill12.out.index
当一个maptask全部溢写完毕之后 可能会生成多个溢写文件 ,这个时候就会进行归并排序
创建file.out文件 从多个溢写文件中一个分区一个分区的拉取过来进行合并输出到file.out中
这个过程是根据索引来进行的 效率高 最终形成一个文件 文件内以分区聚集,分区内key有序
自此 map端的shuffle阶段结束
当map结束之后 会向tasktracker汇报 这里tasktracker其实就是datanode tasktracker再通过心跳机制汇报给jobtracker
reduce会不断向jobtracker获取map的输出文件位置 当获取到之后 会进行copy
reduce端一般会边copy边排序
这里还要说一个提高效率的方法 可以开启map端压缩 因为实际生产环境 reducetask和maptask可能不在同一台机器上 这样就会有网络传输
开启压缩可以有效的减少网络传输量
复制过来的数据优先放到内存中 因为会有多个maptask 所以就会从多个maptask拉取数据 在内存中每个maptask对应一块数据,多达到一定数量时
开始merge到磁盘上生成一个文件 如果maptask个数和数据量很小 那就会呆在内存中
如果有多个merge文件 就会进行一次合并 成大文件
shuffle阶段结束了
之后就是程序员自己写的reduce方法
处理数据 将最后的结果数据
在shuffle过程中生成的溢写文件 最后会被删除
我觉得应该是在程序完成之后 或者时间限制?
这里放几个觉得有帮助的链接
源码解析 https://blog.csdn.net/qq_37163925/article/details/105641490
MapReduce的shuffle详解 https://blog.csdn.net/u014374284/article/details/49205885

浙公网安备 33010602011771号