map和reduce是hadoop的核心功能,hadoop正是经过多个map和reduce的并行运行来实现任务的分布式并行计算,从这个观点来看,若是将map和reduce的数量设置为1,那么用户的任务就没有并行执行,可是map和reduce的数量也不能过多,数量过多虽然能够提升任务并行度,可是太多的map和reduce也会致使整个hadoop框架由于过分的系统资源开销而使任务失败。因此用户在提交map/reduce做业时应该在一个合理的范围内,这样既能够加强系统负载匀衡,也能够下降任务失败的开销。node
1 map的数量并发
map的数量一般是由hadoop集群的DFS块大小肯定的,也就是输入文件的总块数,正常的map数量的并行规模大体是每个Node是10~100个,对于CPU消耗较小的做业能够设置Map数量为300个左右,可是因为hadoop的没一个任务在初始化时须要必定的时间,所以比较合理的状况是每一个map执行的时间至少超过1分钟。具体的数据分片是这样的,InputFormat在默认状况下会根据hadoop集群的DFS块大小进行分片,每个分片会由一个map任务来进行处理,固然用户仍是能够经过参数mapred.min.split.size参数在做业提交客户端进行自定义设置。还有一个重要参数就是mapred.map.tasks,这个参数设置的map数量仅仅是一个提示,只有当InputFormat 决定了map任务的个数比mapred.map.tasks值小时才起做用。一样,Map任务的个数也能经过使用JobConf 的conf.setNumMapTasks(int num)方法来手动地设置。这个方法可以用来增长map任务的个数,可是不能设定任务的个数小于Hadoop系统经过分割输入数据获得的值。固然为了提升集群的并发效率,能够设置一个默认的map数量,当用户的map数量较小或者比自己自动分割的值还小时可使用一个相对交大的默认值,从而提升总体hadoop集群的效率。负载均衡
2 reduece的数量框架
reduce在运行时每每须要从相关map端复制数据到reduce节点来处理,所以相比于map任务。reduce节点资源是相对比较缺乏的,同时相对运行较慢,正确的reduce任务的个数应该是0.95或者1.75 *(节点数 ×mapred.tasktracker.tasks.maximum参数值)。若是任务数是节点个数的0.95倍,那么全部的reduce任务可以在 map任务的输出传输结束后同时开始运行。若是任务数是节点个数的1.75倍,那么高速的节点会在完成他们第一批reduce任务计算以后开始计算第二批 reduce任务,这样的状况更有利于负载均衡。同时须要注意增长reduce的数量虽然会增长系统的资源开销,可是能够改善负载匀衡,下降任务失败带来的负面影响。一样,Reduce任务也可以与 map任务同样,经过设定JobConf 的conf.setNumReduceTasks(int num)方法来增长任务个数。分布式
3 reduce数量为0oop
有些做业不须要进行归约进行处理,那么就能够设置reduce的数量为0来进行处理,这种状况下用户的做业运行速度相对较高,map的输出会直接写入到 SetOutputPath(path)设置的输出目录,而不是做为中间结果写到本地。同时Hadoop框架在写入文件系统前并不对之进行排序。性能
map red.tasktracker.map.tasks.maximum 这个是一个task tracker中可同时执行的map的最大个数,默认值为2,看《pro hadoop》:it is common to set this value to the effective number of CPUs on the node
把ob分割成map和reduce,合理地选择Job中 Tasks数的大小能显著的改善Hadoop执行的性能。增长task的个数会增长系统框架的开销,但同时也会加强负载均衡并下降任务失败的开销。一个极端是1个map、1个reduce的状况,这样没有任务并行。另外一个极端是1,000,000个map、1,000,000个reduce的状况,会因为框架的开销过大而使得系统资源耗尽。
Map任务的数量
Map的数量常常是由输入数据中的DFS块的数量来决定的。这还常常会致使用户经过调整DFS块大小来调整map的数量。正确的map任务的并行度彷佛应该是10-100 maps/节点,尽管咱们对于处理cpu运算量小的任务曾经把这个数字调正到300maps每节点。Task的初始化会花费一些时间,所以最好控制每一个 map任务的执行超过一分钟。
实际上控制map任务的个数是很 精妙的。mapred.map.tasks参数对于InputFormat设定map执行的个数来讲仅仅是一个提示。InputFormat的行为应该把输入数据总的字节值分割成合适数量的片断。可是默认的状况是DFS的块大小会成为对输入数据分割片断大小的上界。一个分割大小的下界能够经过一个mapred.min.split.size参数来设置。所以,若是你有一个大小是10TB的输入数据,并设置DFS块大小为 128M,你必须设置至少82K个map任务,除非你设置的mapred.map.tasks参数比这个数还要大。最终InputFormat 决定了map任务的个数。
Map任务的个数也能经过使用JobConf 的 conf.setNumMapTasks(int num)方法来手动地设置。这个方法可以用来增长map任务的个数,可是不能设定任务的个数小于Hadoop系统经过分割输入数据获得的值。
Reduce任务的个数
正确的reduce任务的 个数应该是0.95或者1.75 ×(节点数 ×mapred.tasktracker.tasks.maximum参数值)。若是任务数是节点个数的0.95倍,那么全部的reduce任务可以在 map任务的输出传输结束后同时开始运行。若是任务数是节点个数的1.75倍,那么高速的节点会在完成他们第一批reduce任务计算以后开始计算第二批 reduce任务,这样的状况更有利于负载均衡。
目前reduce任务的数量 因为输出文件缓冲区大小(io.buffer.size × 2 ×reduce任务个数 << 堆大小),被限制在大约1000个左右。直到可以指定一个固定的上限后,这个问题最终会被解决。
Reduce任务的数量同时也控制着输出目录下输出文件的数量,可是一般状况下这并不重要,由于下一阶段的 map/reduce任务会把他们分割成更加小的片断。
Reduce任务也可以与 map任务同样,经过设定JobConf 的conf.setNumReduceTasks(int num)方法来增长任务个数。this