基本概念
在python和swift中,map,reduce都是一种高阶函数(还有filter),那么什么是高阶函数呢?这里引用一下廖雪峰大神的总结,高阶函数就是指函数参数可以接收其他函数,还有一种函数叫作偏函数,就是指函数的返回值是一个函数。
高阶函数和偏函数的概念可以阅读函数式编程一书得到参考
java8的lambda表达式就是一种高阶函数的实现。
好吧,回归正题,那么什么是map,什么又是reduce呢?
map:map就是指把输入的数据集中的每一个元素进行处理后输出,这种输入输出通常是键值对形式的。
reduce:reduce的英文释义是规约,也就是说reduce函数是将一定的数据集进行循环的处理得到最终的结果。比如找出每个数据集中的最大值。
Mapper和Reducer
Mapper是泛型类型,分别是map函数的输入键,输入值,输出建和输出值,hadoop在java自带的基本类型之上还封装了一套适用于网络序列化传输的基本类型,这些类型位于or.apache.hadoop.io包中,例如Text类型相当于java的String类型。
Reducer也是泛型类型,类型参数和Mapper一样,Reducer提供了强大的数据比较和抽取能力。
Job是用来指定作业执行规范的,主要包括如下几步:
- 设置作业完整的类名
- 设置作业名称
- 设置输入和输入源(可以来自网络,可以来自文件系统)
- 设置map(即对数据进行处理的Mapper实现类)和设置reduce(Reducer的实现类)。
新旧api差别
参考官网
MapReduce的横向(水平)扩展
为了实现横向扩展,需要将数据存储在类似于HDFS的分布式文件系统中。
在MapReduce的作业中,有两类节点控制着作业的执行,一类是jobtracker(作业节点)和一系列的tasktracker(任务节点),一个作业是由多个任务(map任务和reduce任务)组成的。
Hadoop将数据分为大小相等的数据块,每个数据块就是一个分片,并且为每个分片指定一个map任务,由该任务来运行用户自定义的map函数从而处理分片中的每条记录。
分片的大小决定了程序的效率和资源的利用率,如果分片太小,那么管理分片的总时间和构建map任务的时间将会决定整个处理时间,如果分片太大,又没有充分利用map函数提供的处理能力,所以合适的分片大小至关重要。一个合理的分片大小大概是HDFS的一个块的大小。默认是64MB。如果超过了该大小,那么输入源的数据就会存储在两个机架上面,这样就会产生网络传输,降低了效率。
对于map任务,一般运行在输入数据存储的机器上,这样不需要使用网络带宽资源,提高了IO效率。如果该map任务在处理其他的任务,则需要协调其他机架上面的map任务来进行处理,这样还是会产生网络传输。但是这么做,会大大的减少这种情况的发生。
map任务的输出一般都是存储在任务执行的机器上面,因为map输出的数据大多是一个中间数据,只需要临时存储,在传给reduce任务处理之后,就可以删除该中间结果。如果中间数据传输给reduce任务失败,则会在另一个节点上重新运行map任务重新传输从而避免再次失败。
reduce任务可以接收来自多个map任务的输出,这之间复杂的数据传输流称为shuffle。shuffle就是怎样把map task的输出结果有效地传送到reduce端,也可以理解为 Shuffle描述着数据从map task输出到reduce task输入的这段过程。
下图是官方的shuffle解释图
shuffle参考资料
combiner
为了减少map和reduce之间的数据传输量,充分利用集群之间的带宽,可以对map的输出执行一次或者多次的combiner函数,相当于对于单个map进行的规约操作(reduce是对于多个map任务的规约).但是combiner的适用场景有限,例如平均数的计算可能就不适用-((x+y+z+a)/4+(b+c)/2)/2!=(a+b+c+x+y+z)/6,所以该函数的适用范围为对分片数据规约不会影响整个结果的场景。
Streaming API
Streaming API 使得我们可以用其他编程语言实现自己的map和reduce函数,例如用c++实现,提高程序的处理效率。
该API使用标准输入输出流作为hadoop和不同语言编写的map和reduce任务之间的接口。
当使用Streaming时需要在hadoop的运行命令里面指定streaming.jar文件的位置从而让hadoop支持其他语言。
网友评论