码迷,mamicode.com
首页 > 其他好文 > 详细

Hadoop平台优化

时间:2016-01-31 21:29:04      阅读:341      评论:0      收藏:0      [点我收藏+]

标签:

一:概述

随着企业要处理的数据量越来越大,MapReduce思想越来越受到重视。Hadoop是MapReduce的一个开源实现,由于其良好的扩展性和容错性,已经得到越来越广泛的应用。

二:存在问题:

Hadoop作为一个基础数据处理平台,虽然其应用价值已经得到大家认可,但仍然存在问题,以下是主要几个:

1:Namenode/jobtracker单点故障

 Hadoop采用的是master/slaves架构,该架构管理起来比较简单,但存在致命的单点故障和空间容量不足等缺点,这已经严重影响了Hadoop的可扩展性。

2:jobtracker同时进行监控和调度,负载过大

为了解决该问题,yahoo已经开始着手设计下一代Hadoop MapReduce(见参考资料1)。他们的主要思路是将监控和调度分离,独立出一个专门的组件进行监控,而jobtracker只负责总体调度,至于局部调度,交给作业所在的client。

3: 数据处理性能

很多实验表明,其处理性能有很大的提升空间。Hadoop类似于数据库,可能需要专门的优化工程师根据实际的应用需要对Hadoop进行调优,有人称之为“Hadoop Performance Optimization” (HPO)。

 

三:总体优化思路

为了提高Hadoop的数据处理性能,很多人开始优化Hadoop。总体看来,对于Hadoop,当前主要有几个优化思路:

1:从应用程序角度进行优化

由于mapreduce是迭代逐行解析数据文件的,怎样在迭代的情况下,编写高效率的应用程序,是一种优化思路。

2.:对Hadoop参数进行调优

当前hadoop系统有190多个配置参数,怎样调整这些参数,使hadoop作业运行尽可能的快,也是一种优化思路。

3:从系统实现角度进行优化

这种优化难度是最大的,它是从hadoop实现机制角度,发现当前Hadoop设计和实现上的缺点,然后进行源码级地修改。该方法虽难度大,但往往效果明显。

 

  以上三种思路出发点均是提高hadoop应用程序的效率。实际上,随着社会的发展,绿色环保观念也越来越多地融入了企业,因而很多人开始研究Green Hadoop,即怎样让Hadoop完成相应数据处理任务的同时,使用最少的能源。除了学术界的优化,工业界也在不断进行优化以适应自己公司的产品需要,主要有:
(1):Baidu公司。baidu对Hadoop中关键组件使用C++进行了重写(包括map, shuffler和reducer等),经他们内部测试(5 nodes,40GB data),效率提升了约20%。
(2):淘宝。淘宝针对自己集群特点(作业小,slot多,作业之间有依赖,集群共享,有些作业有时效性),对jobtracker和namenode进行了优化,据其官方博客称,其jobtracker有较大性能提升,且namenode吞吐量提升了8+倍。但其具体优化方法,未公开。

 

四:具体优化

1:从应用程序角度进行优化

 

1.1: 避免不必要的reduce任务

如果要处理的数据是排序且已经分区的,或者对于一份数据, 需要多次处理, 可以先排序分区;然后自定义InputSplit, 将单个分区作为单个mapred的输入;在map中处理数据, Reducer设置为空。
这样, 既重用了已有的 “排序”, 也避免了多余的reduce任务。

 

 

1.2:外部文件引入

有些应用程序要使用外部文件,如字典,配置文件等,这些文件需要在所有task之间共享,可以放到分布式缓存DistributedCache中(或直接采用-files选项,机制相同)。
更多的这方面的优化方法,还需要在实践中不断积累。

 

 

1.3: 为job添加一个Combiner

为job添加一个combiner可以大大减少shuffle阶段从map task拷贝给远程reduce task的数据量。一般而言,combiner与reducer相同。

 

 

1.4: 根据处理数据特征使用最适合和简洁的Writable类型

Text对象使用起来很方便,但它在由数值转换到文本或是由UTF8字符串转换到文本时都是低效的,且会消耗大量的CPU时间。当处理那些非文本的数据时,可以使用二进制的Writable类型,如IntWritable, FloatWritable等。二进制writable好处:避免文件转换的消耗;使map task中间结果占用更少的空间。

 

1.5:重用Writable类型

很多MapReduce用户常犯的一个错误是在一个map()/reduce()方法中每个输出都创建Writable对象。例如,你的WordCount Mapper中的方法可能这样写:

 

[java] view plain copy
 
  1. public void map(...) {  
  2.    
  3.   …  
  4.    
  5.   for (String word : words) {  
  6.    
  7.     output.collect(new Text(word), new IntWritable(1));  
  8.    
  9.   }  
  10.    
  11. }  

这样会导致程序分配出成千上万个短周期的对象。Java垃圾收集器就要为此做很多工作。更有效的写法是:

 

 

[java] view plain copy
 
  1. class MyMapper … {  
  2.    
  3.   Text wordText = new Text();  
  4.    
  5.   IntWritable one = new IntWritable(1);  
  6.    
  7.   public void map(...) {  
  8.    
  9.     for (String word: words) {  
  10.    
  11.       wordText.set(word);  
  12.    
  13.       output.collect(wordText, one);  
  14.    
  15.     }  
  16.    
  17.   }  
  18.    
  19. }  

 

 

1.6:使用StringBuffer而不是String

 

当需要对字符串进行操作时,使用StringBuffer而不是String,String是read-only的,如果对它进行修改,会产生临时对象,而StringBuffer是可以修改的,不会产生临时对象。

1.7:调试

最重要,也是最基本的,是要掌握MapReduce程序调试方法,跟踪程序的瓶颈。具体参考:http://www.cloudera.com/blog/2009/12/7-tips-for-improving-mapreduce-performance/

 

2.对参数进行优化

2.1:Linux文件系统参数调优

2.1.1:noatime和nodiratime属性

文件挂载时设置这两个属性可以明显提高性能。。默认情况下,Linux ext2/ext3 文件系统在文件被访问、创建、修改时会记录下文件的时间戳,比如:文件创建时间、最近一次修改时间和最近一次访问时间。如果系统运行时要访问大量文件,关闭这些操作,可提升文件系统的性能。Linux 提供了 noatime 这个参数来禁止记录最近一次访问时间戳。:2

2.1.2: readahead buffer
调整linux文件系统中预读缓冲区地大小,可以明显提高顺序读文件的性能。默认buffer大小为256 sectors,可以增大为1024或者2408 sectors(注意,并不是越大越好)。可使用blockdev命令进行调整。

2.1.3:避免RAID和LVM操作

避免在TaskTracker和DataNode的机器上执行RAID和LVM操作,这通常会降低性能。

2.2:Hadoop通用参数调整

2.2.1:dfs.namenode.handler.count或mapred.job.tracker.handler.count

namenode或者jobtracker中用于处理RPC的线程数,默认是10,较大集群,可调大些,比如64。

2.2.2:dfs.datanode.handler.count

datanode上用于处理RPC的线程数。默认为3,较大集群,可适当调大些,比如8。需要注意的是,每添加一个线程,需要的内存增加。

2.2.3:tasktracker.http.threads

 HTTP server上的线程数。运行在每个TaskTracker上,用于处理map task输出。大集群,可以将其设为40~50。

2.3:HDFS相关配置

2.3.1:dfs.replication

文件副本数,通常设为3,不推荐修改。

2.3.2:dfs.block.size

HDFS中数据block大小,默认为64M,对于较大集群,可设为128MB或者256MB。(也可以通过参数mapred.min.split.size配置)

2.3.3:mapred.local.dir和dfs.data.dir

这两个参数mapred.local.dir和dfs.data.dir 配置的值应当是分布在各个磁盘上目录,这样可以充分利用节点的IO读写能力。运行 Linux sysstat包下的iostat -dx 5命令可以让每个磁盘都显示它的利用率。

2.3.4:mapred.map.tasks.speculative.execution=false且mapred.reduce.tasks.speculative.execution=false

推测执行在整个集群上关闭,特定需要的作业单独开启,一般可以省下约5%~10%的集群资源。

2.4:map/reduce相关配置

2.4.1:mapred.tasktracker.map.tasks.maximum/mapred.tasktracker.reduce.tasks.maxinum

同时运行在TaskTracker上的最大map/reduce task数(默认为2),一般设为(core_per_node)/2~2*(cores_per_node),增大后意味着单机可以并行执行多个任务(当然这也消耗内存资源)。

2.4.2:io.sort.factor

当一个map task执行完之后,本地磁盘上(mapred.local.dir)有若干个spill文件,map task最后做的一件事就是执行merge sort,把这些spill文件合并成一个文件(partition)。执行merge sort的时候,每次同时打开多少个spill文件由该参数决定。打开的文件越多,不一定merge sort就越快,所以要根据数据情况适当调整。

2.4.3:mapred.child.java.opts

设置JVM堆的最大可用内存,需从应用程序角度进行配置。

2.4.4:mapred.job.reuse.jvm.num.tasks=-1

开启jvm重用,默认值为1表示一个Map任务或Reduce任务会对应单独的一个JVM,也就是说启动一个Map任务或Reduce任务都会启动一个JVM,非常消耗资源,如果设置为-1,则表示只要是同一个job的task(无所谓多少个),都可以按顺序在一个JVM上连续执行。如果task 属于不同的job则重用无效,即不同Job的task需要不同的JVM来运行。

 

2.5:map task相关配置

2.5.1:io.sort.mb

Map task的输出结果和元数据在内存中所占的buffer总大小。默认为100M,对于大集群,可设为200M。当buffer达到一定阈值,会启动一个后台线程来对buffer的内容进行排序,然后写入本地磁盘(一个spill文件)。

2.5.2:io.sort.spill.percent

这个值就是上述内存缓冲区溢写的阈值,默认为0.8,即80%,当内存缓冲区中的数据达到这个阈值的时候,后台线程会启动并且将内存缓冲区中的数据溢写到磁盘。

2.5.3:io.sort.record

io.sort.mb中分配给元素局的内存百分比,默认是0.05。这个需要根据应用程序进行调整。

2.5.4:mapred.min.split.size=268435456

增加InputSplit的大小,因为一个InputSplit对应一个Map任务,InputSplit个数减少了,对应的Map任务也就减少了,启用Map任务就是重新启动一个JVM,非常消耗资源,所以说增加InputSplit的大小可以提高效率,这个参数只有设置的比hadoop数据块(dfs.block.size默认为64MB)大的时候才生效,否则走hadoop默认的。

2.5.5:mapred.compress.map.output/ mapred.output.compress

中间结果和最终结果是否要进行压缩,如果是,指定压缩方式(mapred.compress.map.output.codec/ mapred.output.compress.codec)。推荐使用LZO(com.hadoop.compression.lzo.LzoCodec)压缩。Intel内部测试表明,相比未压缩,使用LZO压缩的TeraSort作业运行时间减少60%,且明显快于Zlib压缩。

2.6:reduce task相关配置

2.6.1:mapred.reduce.parallel.copies

Reduce shuffle阶段copier线程数。默认是5,对于较大集群,可调整为16~25。

 

3.从系统实现角度进行优化

参考:http://dongxicheng.org/mapreduce/hadoop-optimization-1/

 

文章来自:董的博客

Hadoop平台优化

标签:

原文地址:http://www.cnblogs.com/thinkpad/p/5173765.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!