MapReduce的详细流程
不管是maptask还是reducetask 启动以后进程名都叫yarn child
由applicationmaster启动上面的yarn child
数据来源
由客户端负责划分输入切片:
扫描输入目录中的所有文件
遍历每一个文件
按照128M规格划分范围
例如一个200M的文件就能划分成两个split,split0 0-128M 第二个切片时split1 128-200M
把划分好的若干个切片放入到arraylist,然后序列化出来形成一个文件 job.split
am看到这个文件就知道有多少个切片 就知道该起几个maptask,也知道哪个maptask读哪个切片范围
maptask里的类textinputformat.getRecordReader()方法返回一个LineRecordReader对象 在一个切片里读取一行字符
返回的是一对kv k是起始偏移量 v是行内容
在LineRecordReader这个类的构造器里调用next方法和createkey方法 每调用一次就生成一对kv 调用自定义的map传给用户自定义的mapper让用户自己去处理
最后调用context.write(k,v)
mapoutputcollector这个类会去拿上面的kv序列化以后放在缓存环里 超过80%就spiller溢写到磁盘去,溢写之前先在内存环中对数据进行一个分区(按partion.getParttion()),排序(按key的compareto)
在做排序分区的时候 数据还是继续写的知识写在那剩余的20%内存环里
排序分区很快做完以后就写到磁盘里了 这个溢出文件放在maptask运行机器的本地磁盘 生成了很多个小文件 这些小文件内部是分区且有序的
会调用一个类merge工具类把这些小文件合并成一个大文件,合并的过程也是分区且有序的 因为前面的小文件本身就是分区且有序的 最终虽然只是一个大文件 但是其实逻辑分区是有多个的 而且同时还会生成一个对应的分区索引文件 里面会指明0分区是哪个偏移量到哪个偏移量 1分区是哪个偏移量到哪个偏移量
最终所有的maptask都在本地生成这么一个大文件+分区索引文件 maptask进程就结束了 . 这个大文件放在nodemanager的web程序document目录中
这个时候reduceTask上场 去多个nodemanager的 document去下载文件的0号区 得到多个文件 这多个文件中 一个文件可能也不全部是key相同的 所以也要做一个merge sort 根据key来meger 得到的结果那就是key相同的业务 然后把合并排序好以后的大文件发给用户自定义的reducer类 (k,迭代器,context) 这个大文件所有的数据都放入迭代器里 通过分组比较器来断开不同key的数据 所以看起来像是相同key为一组 其实是一个一个的给 靠分组比较器来断开
一个reducetask搞完所有分组的之后拿到context.write(k,v) 工具类textoutputformat.getRecordReader()得到RecordWriter对象用write方法写出去生成在配置好的output输出文件夹 如/wordcount/output/part-r-0000....
输入输出组件默认是textinputformat和textoutputformat 这都是针对数据源是txt文本的 实际工作中可以替换成别的文件
例如sequece文件一种序列化文件 大体格式是 key:value key:value key是文件序列化的二进制
浙公网安备 33010602011771号