原文html
Map的输入数据源是多种多样的,咱们使用hdfs做为数据源。文件在hdfs上是以block(块,Hdfs上的存储单元)为单位进行存储的。算法
1.分片缓存
咱们将这一个个block划分红数据分片,即Split(分片,逻辑划分,不包含具体数据,只包含这些数据的位置信息),那么上图中的第一个Split则对应两个个文件块,第二个Split对应一个块。须要注意的是一个Split只会包含一个File的block,不会跨文件框架
2. 数据读取和处理函数
当咱们把数据块分好的时候,MapReduce(如下简称mr)程序将这些分片以key-value的形式读取出来,而且将这些数据交给用户自定义的Map函数处理。优化
3.spa
用户处理完这些数据后一样以key-value的形式将这些数据写出来交给mr计算框架。mr框架会对这些数据进行划分,此处用进行表示。不一样颜色的partition矩形块表示为不一样的partition,同一种颜色的partition最后会分配到同一个reduce节点上进行处理。线程
Map是如何将这些数据进行划分的?翻译
默认使用Hash算法对key值进行Hash,这样既能保证同一个key值的数据划分到同一个partition中,又能保证不一样partition的数据梁是大体至关的。3d
总结:
1.一个map指挥处理一个Split
2.map处理完的数据会分红不一样的partition
3.一类partition对应一个reduce
那么一个mr程序中 map的数量是由split的数量决定的,reduce的数量是由partiton的数量决定的。
Shuffle,翻译成中文是混洗。mr没有排序是没有灵魂的,shuffle是mr中很是重要的一个过程。他在Map执行完,Reduce执行前发生。
数据通过用户自定的map函数处理完成以后,数据会放入内存中的环形缓冲区以内,,他分为两个部分,数据区和索引区。数据区是存放用户真实的数据,索引区存放数据对应的key值,partition和位置信息。当环形缓冲区数据达到必定的比例后,会将数据溢写到一个文件之中,即途中的spill(溢写)过程。
在溢写前,会将数据根据key和partition进行排序,排好序以后会将数据区的数据按照顺序一个个写入文件之中。这样就能保证文件中数据是按照key和parttition进行排序的。最后会将溢写出的一个个小文件合并成一个大的文件,而且保证在每个partition
中是按照Key值有序的。
总结:
reduce节点会将数据拷贝到本身的buffer缓存区中,当缓存区中的数据达到必定的比例的时候,一样会发生溢写过程,咱们任然要保证每个溢写的文件是有序的。与此同时,后台会启一个线程,将这些小文件合并成一个大文件,通过一轮又一轮的合并,最后将这些文件合并成一个大的数据集。在这个数据集中,数据是有序的,相同的key值对应的value值是挨在一块儿的。最后,将这些数据交给reduce程序进行聚合处理。
总结:
在map处理完以后,reduce节点会将各个map节点上属于本身的数据拷贝到内存缓冲区中,最后将数据合并成一个大的数据集,而且按照key值进行聚合,把聚合后的value值做为iterable(迭代器)交给用户使用,这些数据通过用户自定义的reduce函数进行处理以后,一样会以key-value的形式输出出来,默认输出到hdfs上的文件。
咱们说mr程序最终是要将数据按照key值进行聚合,对value值进行计算,那么咱们是否是能够提早对聚合好的value值进行计算?of course,咱们将这个过程称为Combine。哪些场景能够进行conbine优化。以下。
Map端:
1. 在数据排序后,溢写到磁盘前,运行combiner。这个时候相同Key值的value值是挨在一块儿的,能够对这些value值进行一次聚合计算,好比说累加。
2. 溢写出的小文件合并以前,咱们也能够执行一次combiner,须要注意的是mr程序默认至少存在三个文件才进行combiner,不然mr会认为这个操做是不值得的。固然这个值能够经过min.num.spills.for.combine设置。
Reduce端:
送上整个MR过程图