文章目录
MapReduce:简单编程好助手
1. 简介
- MapReduce 是一种Hadoop生态的程序模型(programming model)。 它依赖于YARN来计划和执行并行过程(基于HDFS的分布式文件块),一些工具直接用了它的模型来为其他的程序模型提供更高级别的界面,比如:Hive,pig
- Hive:在前面提到过,Hive有一个类似sql的接口,它增加了帮助进行关系数据建模的功能。
- Pig:Pig是一种高级数据流语言,它增加了帮助进行流程图建模(map modeling)的功能。
传统的并行编程需要很多的专业知识,同时在编写运行时非常容易出错,而MapReduce就是为了解决这个问题的。
2. 详解/WordCount举例
2.1 详解
Map= apply operation to all elements(补充,map是负责把任务分解成多个任务);
Reduce = summarize operation on elements(补充,reduce是负责把分解之后的多任务处理的结果汇总起来)。这是一种基于函数的编程(matlab既视感啊哈哈哈哈)
举个例子:wordCount() 函数的计算过程
功能:wordCount()
函数( WordCount读取一个或多个文本文件,并计算这些文件中每个单词出现的次数。输出将是一个文本文件,其中包含单词列表及其在输入数据中的出现频率。 )
2.2 过程:
(为了简化过程,我们假想有一个大文件作为输入)具体实现过程可以分为以下三步:
0. 文件被储存到HDFS。 (HDFS通过多个集群的节点(multiple nodes in the cluster)来分离所有的数据块(blocks)。 )这样以来,四个区域被贴上标签(A,B,C,D)
1. Map on each node(MapReduce)在每一个节点进行操作(map operation)(这里可不可以理解为函数调用工作?),当输入部分从HTFS(High Throughput File System)被读取的时候, 会为输入中的每一行调用map。
添加一些详细过程。通过阅读其他人的博客,发现map这一步还可以更细致的分为以下过程:
-
分片(Split):map阶段的输入通常是HDFS上文件,在运行Mapper前,FileInputFormat会将输入文件分割成多个split ——1个split至少包含1个HDFS的Block(默认为64M);然后每一个分片运行一个map进行处理。
-
执行(Map):对输入分片中的每个键值对调用map()函数进行运算,然后输出一个结果键值对。(map generates key-value paris)wordCount的key即是计算word的数量
这里强调一点:map移动到每个包含文件数据块的节点,而不是数据移动到map。这是将计算转移到数据。 -
Partitioner:对map()的输出进行partition,即根据key或value及reduce的数量来决定当前的这对键值对最终应该交由哪个reduce处理。默认是对key哈希后再以reduce task数量取模,默认的取模方式只是为了避免数据倾斜。然后该key/value对以及partitionIdx的结果都会被写入环形缓冲区。
-
溢写(Spill):map输出写在内存中的环形缓冲区,默认当缓冲区满80%,启动溢写线程,将缓冲的数据写出到磁盘。
-
Sort:在溢写到磁盘之前,使用快排对缓冲区数据按照partitionIdx, key排序。(每个partitionIdx表示一个分区,一个分区对应一个reduce)
-
Combiner:如果设置了Combiner,那么在Sort之后,还会对具有相同key的键值对进行合并,减少溢写到磁盘的数据量。
-
合并(Merge):溢写可能会生成多个文件,这时需要将多个文件合并成一个文件。合并的过程中会不断地进行 sort & combine 操作,最后合并成了一个已分区且已排序的文件。
2. Sort and Shuffle: 相同key的配对移动的同一个node下去。Pairs with same key moved to same node。
这里也添加一些详细说明:
广义上Shuffle阶段横跨Map端和Reduce端,在Map端包括Spill过程,在Reduce端包括copy和merge/sort过程。通常认为Shuffle阶段就是将map的输出作为reduce的输入的过程(理解为一个过度承接的过程)
-
Copy过程:Reduce端启动一些copy线程,通过HTTP方式将map端输出文件中属于自己的部分拉取到本地。Reduce会从多个map端拉取数据,并且每个map的数据都是有序的。
-
Merge过程:Copy过来的数据会先放入内存缓冲区中,这里的缓冲区比较大;当缓冲区数据量达到一定阈值时,将数据溢写到磁盘(与map端类似,溢写过程会执行 sort & combine)。如果生成了多个溢写文件,它们会被merge成一个有序的最终文件。这个过程也会不停地执行 sort & combine 操作。
3. Reduce :Add values for same keys 有相同key的,做相加工作。( Shuffle阶段最终生成了一个有序的文件作为Reduce的输入,对于该文件中的每一个键值对调用reduce()
方法,并将结果写到HDFS。 )
3. 拓展:搜索引擎(WordCount和URLs)
思想:稍加修改WordCount算法,使用网络爬虫之后,按单词索引所有的url,这样以来,key不再是指向数字,而是指向url。那么这样操作之后,Sort and Shuffle的输出将会是:
接下来,我们再Reduce “Apple”,结果将会是:
4. 不适用的情况
这篇概述让我们了解了MapReduce适用于哪些类型的任务。虽然MapReduce擅长于类似于我们的应用程序的独立批处理任务,但是有些特定类型的任务是您不希望使用MapReduce的。
- 数据经常变动。如果数据经常改变,MapReduce就会变慢,因为它每次都会读取整个输入数据集。
- **有依赖关系的数据集。**MapReduce模型要求Map和reduce独立执行。这极大地简化了设计人员的工作,因为您不必处理同步问题。然而,这意味着有依赖关系的计算不能用MapReduce来表达。
- 不适合交互式应用程序,因为在交互式应用程序中,结果必须非常快速地呈现给用户,并期望从用户那里获得回报。
许多适合MapReduce的任务类型包括搜索引擎页面排名和主题Map。关于使用MapReduce制作意面酱的阅读资料,请参阅这节课之后的使用MapReduce编程模型的另一个有趣的应用程序。
5. 总结(并行在哪里体现了?
在Map步骤中,存在着并行。这种并行化在输入之上,因为每个分区依次只处理一行。为了实现这种类型的数据并行性,我们必须确定每个并行为了实现这种类型的数据并行性,我们必须确定每个并行的数据粒度(比如这里的一行)
我们在Sort and shuffle 阶段同样看到到并行分组的数据。这一次,并行化是在中间产物之上。也就是说,各个独立的key-value 对。在对中间产品进行分组之后,Reduce步骤并行化,构建一个输出文件。
实际上,数据在每一步都减少到一个更小的集合。