Hadoop平台优化综述
1.???? 概述
随着企业要处理的数据量越来越大,MapReduce思想越来越受到重视。Hadoop是MapReduce的一个开源实现,由于其良好的扩展性和容错性,已得到越来越广泛的应用。Hadoop作为一个基础数据处理平台,虽然其应用价值已得到大家认可,但仍存在很多问题,以下是主要几个:
(1)???? Namenode/jobtracker单点故障。 Hadoop采用的是master/slaves架构,该架构管理起来比较简单,但存在致命的单点故障和空间容量不足等缺点,这已经严重影响了Hadoop的可扩展性。
(2)???? HDFS小文件问题。在HDFS中,任何block,文件或者目录在内存中均以对象的形式存储,每个对象约占150byte,如果有1000 0000个小文件,每个文件占用一个block,则namenode需要2G空间。如果存储1亿个文件,则namenode需要20G空间。这样namenode内存容量严重制约了集群的扩展。
(3)???? jobtracker同时进行监控和调度,负载过大。为了解决该问题,yahoo已经开始着手设计下一代Hadoop MapReduce(见参考资料1)。他们的主要思路是将监控和调度分离,独立出一个专门的组件进行监控,而jobtracker只负责总体调度,至于局部调度,交给作业所在的client。
(4)???? 数据处理性能。 很多实验表明,其处理性能有很大的提升空间。Hadoop类似于数据库,可能需要专门的优化工程师根据实际的应用需要对Hadoop进行调优,有人称之为“Hadoop Performance Optimization” (HPO)。
为了提高其数据性能,很多人开始优化Hadoop。总结看来,对于Hadoop,当前主要有几个优化思路:
(1)? 从应用程序角度进行优化。由于mapreduce是迭代逐行解析数据文件的,怎样在迭代的情况下,编写高效率的应用程序,是一种优化思路。
(2)? 对Hadoop参数进行调优。当前hadoop系统有190多个配置参数,怎样调整这些参数,使hadoop作业运行尽可能的快,也是一种优化思路。
(3) 从系统实现角度进行优化。这种优化难度是最大的,它是从hadoop实现机制角度,发现当前Hadoop设计和实现上的缺点,然后进行源码级地修改。该方法虽难度大,但往往效果明显。
以上三种思路出发点均是提高hadoop应用程序的效率。实际上,随着社会的发展,绿色环保观念也越来越多地融入了企业,因而很多人开始研究Green Hadoop,即怎样让Hadoop完成相应数据处理任务的同时,使用最少的能源(见参考资料[14][15])。
本文主要介绍了当前学术界的一些优化思路,有人试图从Hadoop自动配置角度对Hadoop进行优化,但更多的是从系统实现角度进行优化,概括其优化点和实验效果如下:
(1)?? 论文[6]试图从参数自动调优角度对Hadoop进行优化,论文只给出了可能的解决方案,并未给出实现,因而效果不可知。但它给出了一种Hadoop优化的新思路,即怎样对其190多个配置参数进行自动调整,使应用程序执行效率最高。
(2)? 论文[7]提出prefetching和preshuffling机制,在不同负载不同规模集群下测试,效率提升了约73%。
(3)? 论文[8]研究了影响Hadoop效率的五个因素,并通过提出相应的解决方案,使Hadoop效率提高了2.5~3.5倍。
(4)? 论文[9]为Hadoop提供了一种索引机制– Trojan Index,同时提出了一种高效的join算法– Trojan Join,实验表明,效率比Hadoop和HadoopDB高很多。
除了学术界的优化,工业界也在不断进行优化以适应自己公司的产品需要,主要有:
(1)Baidu公司。baidu对Hadoop中关键组件使用C++进行了重写(包括map, shuffler和reducer等),经他们内部测试(5 nodes,40GB data),效率提升了约20%(见参考资料[4])。
(2)淘宝。淘宝针对自己集群特点(作业小,slot多,作业之间有依赖,集群共享,有些作业有时效性),对jobtracker和namenode进行了优化,据其官方博客称,其jobtracker有较大性能提升,且namenode吞吐量提升了8+倍(见参考资料[5])。但其具体优化方法,未公开。
2.???? 从应用程序角度进行优化
(1) 避免不必要的reduce任务
如果要处理的数据是排序且已经分区的,或者对于一份数据, 需要多次处理, 可以先排序分区;然后自定义InputSplit, 将单个分区作为单个mapred的输入;在map中处理数据, Reducer设置为空。
这样, 既重用了已有的 “排序”, 也避免了多余的reduce任务。
(2)外部文件引入
有些应用程序要使用外部文件,如字典,配置文件等,这些文件需要在所有task之间共享,可以放到分布式缓存DistributedCache中(或直接采用-files选项,机制相同)。
更多的这方面的优化方法,还需要在实践中不断积累。
(3) 为job添加一个Combiner
为job添加一个combiner可以大大减少shuffle阶段从map task拷贝给远程reduce task的数据量。一般而言,combiner与reducer相同。
(4) 根据处理数据特征使用最适合和简洁的Writable类型
Text对象使用起来很方便,但它在由数值转换到文本或是由UTF8字符串转换到文本时都是低效的,且会消耗大量的CPU时间。当处理那些非文本的数据时,可以使用二进制的Writable类型,如IntWritable, FloatWritable等。二进制writable好处:避免文件转换的消耗;使map task中间结果占用更少的空间。
(5) 重用Writable类型
很多MapReduce用户常犯的一个错误是,在一个map/reduce方法中为每个输出都创建Writable对象。例如,你的Wordcout mapper方法可能这样写:
当前主要的解决思路有:
(1)??? Zookeeper。利用分布式系统的可靠协调系统zookeeper维护主从namenode之间的一致性。
(2)??? 热备。添加热备从namenode,主从namenode之间通过分布式协议维护数据一致性。
(3)??? 分布式namespace。多个namenode共同管理底层的datanode。
5.2??? 小文件问题
小文件是指文件size小于HDFS上block大小的文件。这样的文件会给hadoop的扩展性和性能带来严重问题。首先,在HDFS中,任何block,文件或者目录在内存中均以对象的形式存储,每个对象约占150byte,如果有1000 0000个小文件,每个文件占用一个block,则namenode需要2G空间(存两份)。如果存储1亿个文件,则namenode需要20G空间。这样namenode内存容量严重制约了集群的扩展。 其次,访问大量小文件速度远远小于访问几个大文件。HDFS最初是为流式访问大文件开发的,如果访问大量小文件,需要不断的从一个datanode跳到另一个datanode,严重影响性能。最后,处理大量小文件速度远远小于处理同等大小的大文件的速度。每一个小文件要占用一个slot,而task启动将耗费大量时间甚至大部分时间都耗费在启动task和释放task上。
对于Hadoop小文件问题,当前主要有两种解决方案,(1)设计一种工具(比如mapreduce作业)交给用户,让用户自己每隔一段时间将小文件打包成大文件,当前Hadoop本身提供了几个这样的工具,包括Hadoop Archive(Hadoop提供了shell命令),Sequence file(需自己写程序实现)和CombineFileInputFormat(需自己写程序实现)。(2)从系统层面解决HDFS小文件,论文[10][11]介绍了它们思路,大体上说思路基本一致:在原有HDFS基础上添加一个小文件处理模块,当用户上传一个文件时,判断该文件是否属于小文件,如果是,则交给小文件处理模块处理,否则,交给通用文件处理模块处理。小文件处理模块的设计思想是,先将很多小文件合并成一个大文件,然后为这些小文件建立索引,以便进行快速存取和访问。
6.???? 总结
本文档介绍Hadoop现有的优化点,总体来说,对于Hadoop平台,现在主要有三种优化思路,分别为:从应用程序角度角度进行优化;从参数配置角度进行优化;从系统实现角度进行优化。对于第一种思路,需要根据具体应用需求而定,同时也需要在长期实践中积累和总结;对于第二种思路,大部分采用的方法是根据自己集群硬件和具体应用调整参数,找到一个最优的。对于第三种思路,难度较大,但效果往往非常明显,总结这方面的优化思路,主要有以下几个:
(1)??? 对namenode进行优化,包括增加其吞吐率和解决其单点故障问题。当前主要解决方案有3种:分布式namenode,namenode热备和zookeeper。
(2)??? HDFS小文件问题。当Hadoop中存储大量小文件时,namenode扩展性和性能受到极大制约。现在Hadoop中已有的解决方案包括:Hadoop Archive,Sequence file和CombineFileInputFormat。
(3)??? 调度框架优化。在Hadoop中,每当出现一个空闲slot后,tasktracker都需要通过HEARBEAT向jobtracker所要task,这个过程的延迟比较大。可以用task预调度的策略解决该问题。
(4)??? 共享环境下的文件并发存取。在共享环境下,HDFS的随机寻道次数增加,这大大降低了文件存取效率。可以通过优化磁盘调度策略的方法改进。
(5)??? 索引。索引可以大大提高数据读取效率,如果能根据实际应用需求,为HDFS上的数据添加索引,将大大提高效率。