性能调优涉及4个方面:CPU利用率、内存占用情况、磁盘I/O和网络流量。
有很多因素会对HadoopMapReduce性能产生影响。一般说来,与工作负载相关的Hadoop性能优化需要关注以下3个主要方面:系统硬件、系统软件,以及Hadoop基础设施组件的配置和调优/优化。
需要指出的是,Hadoop被归类为高扩展性解决方案,但却不足以归类为高性能集群解决方案。系统管理员可以通过各种配置选项来配置和调优Hadoop集群。性能配置参数主要关注CPU利用率、内存占用情况、磁盘I/O和网络流量。除了Hadoop主要性能参数以外,其他系统参数,如机架间带宽,也可能影响集群的整体性能。
Hadoop可以按照用户需要进行配置和定制,可以通过对安装完成后自动生成的配置文件进行修改来满足应用和集群的特定需要。
配置文件分为两类,即只读默认配置文件和站点特定配置文件。
第一类包括coredefault.xm、hdfsdefault.xml和mapreddefault.xml。
第二类包括coresite.xml、hdfssite.xml和mapredsite.xml。
Hadoop配置文件中有大量变量,通过定义或者修改这些变量,可以满足控制Hadoop配置的需要。这些变量定义在配置文件core-site.xml、hdfs-site.xml和mapred-site.xml中。其中一些变量用于指定系统中特定文件的路径,而其他变量则用于从不同角度调整Hadoop框架,而且可以从不同粒度深入其内部。每个配置文件都有多个用XML格式表示的名称值对(namevaluepair),它们从不同角度定义Hadoop的工作方式。
从系统硬件的角度看,要衡量合理的硬件配置,需要关注性能、可扩展性及成本要求。从软件的角度看,选择运行Hadoop必需的操作系统、JVM(Java虚拟机)、特定的Hadoop版本以及其他软件组件对于性能以及环境的稳定有着重要的意义。任何Hadoop项目,如果要充分获得Hadoop软硬件分布式解决方案带来的好处,其设计、构建、配置以及调优阶段都意义重大。
mapred-site.xml是提高HadoopMapReduce性能的关键配置文件。这个配置文件包含了与CPU、内存、磁盘I/O和网络相关的参数。
1.CPU参数
与CPU相关的两个参数与CPU利用率关联最为密切。通过修改这些变量,可以指定由TaskTracker节点并发运行的map/reduce任务的最大数量。这两个参数默认值为2。
理论上,上述默认值的增加有助于提高CPU利用率,从而提高性能,但这需要根据集群资源精巧地设置,如CPU(是否考虑超线程因素)和可用内存;否则,就会有MapReduce作业和集群性能整体降级的风险。
一个典型问题是:mapper/reducer数量设置为多少才能获得最佳性能?要设置这个值,需要考虑TaskTracker资源(如CPU、内存和磁盘I/O)利用率。而且,还要考虑运行的作业是否是CPU密集型的。
为了厘清这些参数设置,我们假设你拥有10个Hadoop集群节点,每个节点有1个四核CPU。这样,全部守护进程应该不超过10(节点)×4(CPU核)=40个。考虑到需要分别为DataNode守护进程和TaskTracker守护进程各预留1个CPU核,因此留给map/reduce任务的CPU核还剩38个。
不必把mapper和reducer的数量设置为相同的值,因为该项设置依赖于每项任务的CPU利用率,也依赖mapper和reducer完成作业并得到最后结果的方式。你可以把CPU资源分配给mapper和reducer各50%,也可以分配三分之二给mapper,三分之一给reducer,或者其他能够使集群运行最优的分配方式。如果把该值设为−1,Hadoop将使用管理员为mapper和reducer任务分配的全部内存。如果将这个值设置为超过实际CPU核的数目,将会导致密集的CPU上下文切换,这会造成集群性能显著降级。
2.与磁盘I/O相关的参数
为了优化磁盘I/O操作,你需要判断是否需要使用数据压缩,默认情况下这个开关项处于关闭状态。可以通过修改控制压缩的参数默认值来启用数据压缩。mapred.compress.map.output变量启用map输出压缩,mapred.output.compress变量启用作业输出压缩,mapred.map.output.compression.codec变量用于定义压缩的编解码方式。
启用map任务的输出压缩可以有效减少写入存储系统的中间数据量。因此,这会在shuffle阶段和写入阶段加速磁盘写操作,从而减少数据传输的总时间。用压缩技术加速磁盘写操作会在压缩/解压过程中带来额外的CPU开销。
实际经验表明,只有当输入数据量很大而且容易拆分时(如文本文件),才应该启用压缩;否则会造成集群性能的降级。
要获得磁盘I/O的平衡并大幅提升I/O性能,可以使用向多个位置写入的功能,把数据写到每个节点的所有磁盘上。与使用RAID 0数据分条技术相比,使用多个物理设备会带来大约50%的性能提升。
下面的两个参数决定了Hadoop中用来存储数据的位置。可以使用mapred.local.dir指定中间map输出数据的存储位置,而使用dfs.data.dir指定HDFS数据的存储位置。
3.与内存相关的参数
内存资源非常重要,精确分配内存资源可以有效地避免内存交换,并优化Hadoop作业的运行。可以使用与内存相关的参数来设置为MapReduce作业预留的物理内存的数量。下面列出了常用的内存相关参数
mapred.child.ulimit默认值未指定。如果为这个参数指定值,则该值要大于(至少等于)参数mapred.child.java.opts的–Xmx值;否则,Java虚拟机可能无法启动。要正确设定此参数,其值应大于2 × mapred.child.java.opts。使用与内存相关的参数还可以优化合并与排序。有三个参数可以优化MapReduce的合并与排序的性能:
增加io.sort.mb和io.sort.factor的值会为排序与合并操作分配更多的内存。这会减少对磁盘的流量冲击,从而减少mapper和reducer任务的I/O时间。但是,上述变量的增加会导致每一个map任务需要的内存增加,当为每一任务分配的内存不足时,会增加内存垃圾收集活动的开销。
经验表明,磁盘溢写量很大时,以及sort/shuffle阶段I/O时间很长时,io.sort.factor值需要相应加大。当map输出很大,造成map端I/O很频繁时,可以考虑增加io.sort.mb的值。为了避免出现“任务耗尽内存”这样的错误,io.sort.mb的值应该大于0.25 × mapred.child.java.opts 且小于0.5 × mapred.child.java.opts。
通过增加mapred.job.reduce.input.buffer.percent的值可以得到更多的内存缓冲区,从而在reduce阶段减少本地磁盘I/O时间。不过,前面已经提过,如果分配更多内存,就会在释放未用内存时增加垃圾收集的开销。因此,如果map输出很大,以及reduce排序阶段本地磁盘I/O很频繁,就应该分配更多的内存。
4.与网络相关的参数
Hadoop有一个叫做“机架感知”(rack awareness)的概念。系统管理员可以为集群中的每一个DataNode定义机架。Hadoop机架感知非常重要,因为它可以避免数据丢失,而一个好的机架感知配置可以改善网络性能。下面给出的Hadoop建立机架感知的变量。
增加mapred.reduce.parallel.copies的值会增加网络流量,加速map输出的复制过程,但需要消耗更多CPU。建议只在mapper任务产生的输出量非常大的时候才考虑增加这一参数的值。
Hadoop机架感知特性是通过coresite.xml文件中的topology.script.file.name参数配置的。该参数指向一个用户定义的脚本文件,用来决定机架到主机的映射(Rack1:DataNode1,DataNode2……Rack2:DataNode6,DataNode7……)。如果未配置topology.script.file.name参数,同一机架上所有节点的IP地址都传递为/defaultrack。
hdfs-site.xml配置文件包含许多与HDFS存储系统相关的参数,通过修改这些参数可以达到对Hadoop安装定制并调优的目的。文件系统块大小的值是hdfs-site.xml文件中最常用的调优HDFS的参数。这一参数控制着每个map任务将会处理的输入分片的大小。输入分片的大小通过三个主要变量来进行制定:dfs.block.size(hdfs-site.xml中)、mapred.min.split.size 和 mapred.max.split.size (mapred-site.xml中)。
默认情况下,dfs.block.size 设置为67108864 字节(64MB)。增加此值会产生更大的输入分片,因而减少存放在每个DataNode上的块的数量。
map任务的总数依赖于输入数据的大小和总的输入分片的大小。而map输入的大小和HDFS块的大小成正比,如果加大块的大小的同事不对与数据溢流(spill)相关的属性做调整,可能会导致map侧数据溢流。
为了最大化数据吞吐量,块大小应该与输入数据相适应。对于非常大的输入文件,最好用的大数据快(128MB甚至256MB),而对于小文件,用小一些的数据块更好。需要注意的是,通过调整dfs.block.size参数,在写入文
件时,让同一文件系统存在不同块大小的文件是不可能的。
下面是hdfs-site.xml配置文件中可以设置的主要参数:
改变块大小会对很多方面产生影响。多数情况下,采用更大的块大小来拆分文件会减少块的数量,从而减少NameNode上的元数据,这一点对非常大的文件显得非常重要。而且,这也为客户端不经过与NameNode交互而读写更多数据带来可能。
块减少,所需的存储文件的节点数也随之减少。这可能会使并行访问的总体吞吐量降低,还可能会使数据本地任务的调度更加困难。
并行吞吐量降低的同时可能意味着不能获得最大程度的并行性,这会降低运行成本但集群可能利用不够充分。这会增加任务拖延的可能性,而且一个任务的失败可能会导致很多任务返工。块减少还意味着每个任务处理的数据量增大,从而产生额外的读写操作。
core-site.xml配置文件
core-site.xml是Hadoop的主要配置文件之一,它包含了对整个Hadoop通用的配置。它在每个集群中的主机上都存在。基本上,core-site.xml的变量可以改变或者定义分布式文件系统的名字、临时目录以及其他与网络配置相关的参数,如下所示:
对于小规模集群,所有的服务器通畅都是通过一台交换机连接起来的。因此,本地性指标只有两个:on-machine(联机)和off-machine(脱机)。从HDFS像NameNode的本地驱动器加载数据时,NameNode仅调度传输到本地DataNode的一份副本,然后从集群中随机挑选另外两台机器存储数据的复制件。
对于跨多个机架的大型Hadoop集群,就务必保证每个机架上都有数据的复制件。这样,因为复制件的存在,所以在发生交换机故障时才不会造成数据块不可用。
参数io.file.buffer.size 用来设置I/O操作时Hadoop使用的缓冲区的大小。这个参数的默认值为4096字节(4KB)。在现代系统上,为了获取性能增益,这个参数可以增加至65536(64KB)或者131071(128KB)。
参考资料:《Hadoop MapReduce性能优化》