1.MapTask运行机制
第一步: 读取文件
FileInputFormat切片机制:
切片:是将数据进行逻辑上划分成多个split。将每一个split分配给一个对应的maptask处理。block是HDFS上物理上存储的存储的数据,切片是对数据逻辑上的划分。两者之间没有关系,但划分的split的数量与block的数量相等。
我们通常利用FileInputFormat的子类TextInputFormat将文件从磁盘进行读取,并将数据解析成key-value对。通过 getSplit对读取的文件进行切片,切片的数量与block的数量一致,大小默认为128M。RecorderReader对象将对文件按行读取,以\n 作为分隔符,解析成key-value对。key代表行偏移量,value 表示这一行文本内容。
第二步:自定义map逻辑生成key-value对
读取切片中的key,value到自定义的mapper中,重写map函数,对解析成的key,value对进行操作。生成新的key,value对。RecoderReader读取一行执行一次。
第三步:分区
Hadoop提供Partitioner接口进行分区,根据key,value及reduce的数量决定要输出数据,应交由哪个reduceTask进行处理。默认使用HashPartitioner,返回 (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;值决定分区。
第四步:数据写入环形数据缓冲区
将map逻辑后产生的key-value由OutpCollector.collect()写入内存中的环形数据缓冲区。 缓冲区的作用是减少对磁盘的操作。key-value对会被序列化成字节数组和分区后的结果一起存入缓冲区,缓冲区其实相当于一个字节数组。缓冲区的大小限制是100M.当缓冲区的数据大小达到了阈值80%,也就是80M时,会发生“溢写”,会将这80M的数据写到临时磁盘文件中。由单线程执行溢写时,不影响数据的继续存储。当溢写线程启动后,需要对key进行排序。
第五步:规约
当发生溢写,并对序列化的key进行了排序后,实现Combiner,将相同的key的value合并,减少写到磁盘的数据量,Combiner 会优化 MapReduce 的中间结果。
第六步:数据溢出到磁盘
数据处理之后,会将产生的多个磁盘临时文件进行合并 ,生成一个大文件,写入磁盘。并且为这个文件提供了一个索引文件,以记录每个 reduce 对应数据的偏移量。
2.ReduceTask运行机制
1).向maptask拷贝数据,拉取属于属于reducetask自己的数据
2).合并排序。把分散的数据合并成一个大的数据后,还会再对合并后的数据排序。合并可能在内存中,也可能在磁盘中,取决于文件的大小,文件的大小小于内存的就会在内存中运行,大于则会在磁盘中运行。
3).调用reduce逻辑
4).数据输出