1.任务调度
任务调度是hadoop中重要的环节
1.计算方面,hadoop会将任务分配给空闲机器,使所有的任务能公平地分享系统资源。
2.I/O数据流方面,会尽量将map任务分配给InputSplit所在的机器,减少I/O操作。
2.数据预处理与InputSplit的大小
1.mapredue适合处理少量的大数据,所以提交任务时可以对预处理数据进行合并以提高执行效率。
2.如果一个map执行速度快,当一个map任务执行几秒就结束时,就要考虑给它分配更多的数据,通常而言一个map执行时间在1分钟比较合适。
可以设置map输入数据的大小来调节map的运行时间,Hadoop会在处理每个Block后将其作为一个InputSplit,因此合理地设置block块大小是很重 要的调节方式。除此之外,也可以通过合理地设置Map任务的数量来调节Map任务的数据输入。
3.分配map和reduce任务的数量
通过属性
mapred.tasktracker.map.tasks.maximum 设置map任务的最大数量
mapred.tasktracker.reduce.tasks.maximum设置reduce任务最大数量
3.mapreduce的任务数量
1.首先要定义两个概念—Map/Reduce任务槽。Map/Reduce任务槽就是这个集群能够同时运行的Map/Reduce任务的最大数量。比如,在一个具有1200台机器的集群中,设置每台机器最多可以同时运行10个Map任务,5个Reduce任务。那么这个集群的Map任务槽就是12000,Reduce任务槽是6000。任务槽可以帮助对任务调度进行设置
2.map的任务数主要是参考map运行时间设置的,reduce任务数主要参考任务槽来设置的,一般来说,Reduce任务的数量应该是Reduce任务槽的0.95倍或是1.75倍,这是基于不同的考虑来决定的。当Reduce任务的数量是任务槽的0.95倍时,如果一个Reduce任务失败,Hadoop可以很快地找到一台空闲的机器重新执行这个任务。当Reduce任务的数量是任务槽的1.75倍时,执行速度快的机器可以获得更多的Reduce任务,因 此可以使负载更加均衡,以提高任务的处理速度。
(在Hadoop中默认是运行一个Reducer,所有的Reduce任务都会放到单一的Reducer去执行,效率非常低下。为了提高性能,可以适当增大Reducer的数量。最优的Reducer数量取决于集群中可用的Reducer任务槽的数目。Reducer任务槽的数目是集群中节点个数与mapred.tasktracker.reduce.tasks.maximum(默认为2)的乘积,也可以通过MapReduce的用户界面获得)
4. Combine函数
1.Combine函数是用于本地合并数据的函数。在有些情况下,Map函数产生的中间数据会有很多是重复的,比如在一个简单的WordCount程序中,因 为词频是接近与一个zipf分布的,每个Map任务可能会产生成千上万个<the, 1>记录,若将这些记录一一传送给Reduce任务是很耗时的。所以,MapReduce框架运行用户写的combine函数用于本地合并,这会大大减少网络I/O操作的消耗。此时就可以利用combine函数先计算 出在这个Block中单词the的个数。合理地设计combine函数会有效地减少网络传输的数据量,提高MapReduce的效率。
在MapReduce程序中使用combine很简单,只需在程序中添加如下内容:
job.setCombinerClass(combine.class);
在WordCount程序中,可以指定Reduce类为combine函数,具体如下:
job.setCombinerClass(Reduce.class);
5.压缩,减少I/O1.编写MapReduce程序时,可以选择对Map的输出和最终的输出结果进行压缩(同时可以选择压缩方式)。在一些情况下,Map的中间输出可能会很大,对其进行压缩可以有效地减少网络上的数据传输量。对最终结果的压缩虽然会减少数据写HDFS的时间,但是也会对读取产生一定的影响,因此要根据实际情况来选择(第7章中提供了一个小实验来验证压缩的效果)。
6. 自定义comparator
1.在Hadoop中,可以自定义数据类型以实现更复杂的目的,比如,当读者想实现k-means算法(一个基础的聚类算法)时可以定义k个整数的集合。自定义Hadoop数据类型时,推荐自定义comparator来实现数据的二进制比较,这样可以省去数据序列化和反序列化的时间,提高程序的运行效率。