建立环境
部署 Hadoop 环境的步骤
在执行性能调优之前,需要先构建 Hadoop 集群环境。步骤如下:
$HADOOP_HOME
代表解压位置。 $HADOOP_HOME
目录并修改配置文件。
$HADOOP_HOME/conf/masters
中。 $HADOOP_HOME/conf/slaves
中,每个主机一行。 注意:如果使用主机名,就需要通过配置 /etc/hosts
文件确保集群中的所有节点都知道每个主机名。 $HADOOP_HOME/conf/core-site.xml
中以设置 NN IP/端口:
<property>
<name>fs.default.name</name>
<value>hdfs://host001:9000</value>
</property>
|
$HADOOP_HOME/conf/mapred-site.xml
中以设置 JT IP/端口:
<property>
<name> mapred.job.tracker </name>
<value>host002:9001</value>
</property>
|
mapreduce.jobtracker.address
。 $HADOOP_HOME/conf/hdfs-site.xml
中:
<property>
<name>dfs.datanode.dns.nameserver</name>
<value>eth1</value>
<description>The name of the Network Interface from which a data node
should report its IP address.
</description>
</property>
|
$HADOOP_HOME/conf/
目录中。 $HADOOP_HOME/bin
目录。
$./hadoop namenode -format
命令格式化 NN。 start-all.sh
脚本以启动 Hadoop 守护进程。 安装并配置 nmon 性能监视工具
nmon 是一个系统管理、调优和基准测试工具,可以简便地监视大量重要的性能信息。可以在整个性能调优过程中使用 nmon 作为监视工具。按以下步骤安装并配置 nmon,建立自己的性能监视系统:
$NMON_HOME
代表放置 nmon 二进制代码的位置。 /home/hadoop/perf_share
)并通过 NFS 共享它:
$mkdir /home/hadoop/perf_share
/home/hadoop/perf_share *(rw,sync)
$/etc/rc.d/init.d/nfs restart
perf_share
目录:
$mkdir/home/hadoop/perf_share
$mount host002: /home/hadoop/perf_share /home/hadoop/perf_share |
hosts=( shihc008 shihc009 shihc010 shihc011 shihc012 shihc013 shihc014 shihc015
shihc016 shihc017)
# Remove all data in /home/hadoop/perf_share
for host in ${hosts[@]}
do
ssh $host "cd /home/hadoop/perf_share;rm -rf *"
done
# Start nmon on all nodes
for host in ${hosts[@]}
do
ssh $host " /usr/bin/nmon -f -m /home/hadoop/perf_share -s 30 -c 360"
done
|
-f
表示希望把数据保存到文件中,并不在屏幕上显示;-m
表示保存数据的位置;-s 30
表示希望每 30 秒捕捉一次数据;-c 360
表示需要 360 个数据点(即快照),总数据收集时间为 30x360 秒,即 3 小时。 回页首
Hadoop 可配置参数
Hadoop 提供许多配置选项,用户和管理员可以通过它们进行集群设置和调优。core/hdfs/mapred-default.xml
中有许多变量,可以在 core/hdfs/mapred-site.xml
中覆盖它们。一些变量指定系统上的文件路径,而其他变量对 Hadoop 的内部进行深入的调整。
性能调优主要有四个方面:CPU、内存、磁盘 I/O 和网络。本文介绍与这四个方面最相关的参数,您可以使用后面介绍的方法研究 *-default.xml
中的其他参数。
与 CPU 相关的参数: mapred.tasktracker.map
和 reduce.tasks.maximum
决定由任务跟踪器同时运行的 map/reduce 任务的最大数量。这两个参数与 CPU 利用率最相关。这两个参数的默认值都是 2。根据集群的具体情况适当地增加它们的值,这会提高 CPU 利用率,由此提高性能。例如,假设集群中的每个节点有 4 个 CPU,支持并发多线程,每个 CPU 有两个核;那么守护进程的总数不应该超过 4x2x2=16 个。考虑到 DN 和 TT 要占用两个,map/reduce 任务最多可以占用 14 个,所以这两个参数最合适的值是 7。
在 mapred-site.xml
中设置此参数。
与内存相关的参数: mapred.child.java.opts
这是用于 JVM 调优的主要参数。默认值是 -Xmx200m
,这给每个子任务线程分配最多 200 MB 内存。如果作业很大,可以增加这个值,但是应该确保这不会造成交换,交换会严重降低性能。
我们来研究一下这个参数如何影响总内存使用量。假设 map/reduce 任务的最大数量设置为 7,mapred.child.java.opts
保持默认值。那么,正在运行的任务的内存开销为 2x7x200 MB =2800 MB。如果每个工作者节点都有 DN 和 TT 守护进程,每个守护进程在默认情况下占用 1 GB 内存,那么分配的总内存大约为 4.8 GB。
在 mapred-site.xml
中设置此参数。
与磁盘 I/O 相关的参数: mapred.compress.map.output
、mapred.output.compress
和 mapred.map.output.compression.codec
这些参数控制是否对输出进行压缩,其中 mapred.compress.map.output
用于 map 输出压缩,mapred.output.compress
用于作业输出压缩,mapred.map.output.compression.codec
用于压缩代码。这些选项在默认情况下都是禁用的。
启用输出压缩可以加快磁盘(本地/Hadoop Distributed File System (HDFS))写操作,减少数据传输的总时间(在 shuffle 和 HDFS 写阶段),但是在另一方面压缩/解压过程会增加开销。
根据个人经验,启用压缩对于使用随机键/值的操作序列是无效的。建议只在处理大量有组织的数据(尤其是自然语言数据)时启用压缩。
在 mapred-site.xml
中设置这些参数。
io.sort.mb 参数
这个参数设置用于 map 端排序的缓冲区大小,单位是 MB,默认值是 100。这个值越大,溢出到磁盘就越少,因此会减少 map 端的 I/O 时间。注意,增加这个值会导致每个 map 任务需要的内存增加。
根据个人经验,在 map 输出很大而且 map 端 I/O 很频繁的情况下,应该尝试增加这个值。
在 mapred-site.xml
中设置此参数。
io.sort.factor 参数
这个参数设置在 map/reduce 任务中同时合并的输入流(文件)数量。这个值越大,溢出到磁盘就越少,因此会减少 map/reduce 的 I/O 时间。注意,如果给每个任务分配的内存不够大,增加这个值可能会导致更多垃圾收集活动。
根据个人经验,如果出现大量溢出到磁盘,而且排序和 shuffle 阶段的 I/O 时间很高,就应该尝试增加这个值。
在 mapred-site.xml
中设置此参数。
mapred.job.reduce.input.buffer.percent 参数
这个参数设置用于在 reduce 阶段保存 map 输出的内存的百分比(相对于最大堆大小),默认值是 0。当 shuffle 结束时,内存中剩余的 map 输出必须少于这个阈值,然后 reduce 阶段才能够开始。这个值越大,磁盘上的合并就越少,因此会减少 reduce 阶段本地磁盘上的 I/O 时间。注意,如果给每个任务分配的内存不够大,增加这个值可能会导致更多垃圾收集活动。
根据个人经验,如果 map 输出很大而且在 reduce 到排序阶段本地磁盘 I/O 很频繁,应该尝试增加这个值。
在 mapred-site.xml
中设置此参数。
mapred.local.dir 和 dfs.data.dir 参数
这两个参数决定把 Hadoop 中的数据放在什么地方,mapred.local.dir
决定存储 MapReduce 中间数据( map 输出数据)的位置,dfs.data.dir
决定存储 HDFS 数据的位置。
根据个人经验,把这些位置分散在每个节点上的所有磁盘上可以实现磁盘 I/O 平衡,因此会显著改进磁盘 I/O 性能。
在 mapred-site.xml
中设置 mapred.local.dir
,在 hdfs-site.xml
中设置 dfs.data.dir
。
与网络相关的参数: topology.script.file.name
这个参数指向一个用户定义的脚本,这个脚本判断机架-主机(rack-host)映射以配置机架感知。在 core-site.xml
文件中设置此参数。
机架感知是对于提高网络性能最重要的配置,强烈建议按 http://hadoop.apache.org/common/docs/current/cluster_setup.html#Hadoop+Rack+Awareness 和 http://wiki.apache.org/hadoop/topology_rack_awareness_scripts 上的说明配置它。
mapred.reduce.parallel.copies 参数
这个参数决定把 map 输出复制到 reduce 所使用的线程数量,默认值是 5。增加这个值可以提高网络传输速度,加快复制 map 输出的过程,但是也会增加 CPU 使用量。
根据个人经验,增加这个值的效果不太明显,建议只在 map 输出非常大的情况下增加这个值。
注意:上面列出的参数名都是 Hadoop 0.20.x 中的;如果使用 0.21.0,名称可能有变化。除了 Hadoop 参数之外,还有一些会影响总体性能的系统参数,比如机架间带宽。
回页首
如何调优和提高性能
介绍了上面的预备知识之后,现在讨论如何调优和提高性能。可以把整个过程划分为以下步骤。
步骤 1:选择测试基准
整个 Hadoop 集群的性能由两个方面决定:HDFS I/O 性能和 MapReduce 运行时性能。Hadoop 本身提供几个基准,比如用于 HDFS I/O 测试的 TestDFSIO
和 dfsthroughput
(包含在 hadoop-*-test.jar
中)、用于总体硬件测试的 Sort
(包含在 hadoop-*-examples.jar
中)和 Gridmix
(它模拟网格环境中的混合工作负载,放在 $HADOOP_HOME/src/benchmarks
目录中)。可以根据自己的测试需求选择任何基准。
在所有这些基准中,当输入数据很大时,Sort
可以同时反映 MapReduce 运行时性能(在 “执行排序” 过程中)和 HDFS I/O 性能(在 “把排序结果写到 HDFS” 过程中)。另外,Sort
是 Apache 推荐的硬件基准。(可以通过 Hadoop Wiki 找到相关信息。)因此,本文使用 Sort
作为示例测试基准讲解性能调优方法。
步骤 2:构建基线
注意:把上面提到的 start_nmon.sh
脚本和以下脚本放在存储测试结果的目录中。
baseline_test.sh
#!/bin/sh
# since there are 10 nodes, should write 50 GB file on each
fSize=5368709120
$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-0.20.1-examples.jar
randomwriter -D
test.randomwrite.bytes_per_map=$fSize /rand_$fSize 2>&1 | tee
./testRes/randomwriter_$fSize.out
mkdir -p ./testRes/nmonFiles
# run three cycles to get a more precise result
for runtimes in {a,b,c}
do
./ run_sort_baseline.sh $fSize $runtimes
done
|
run_sort_baseline.sh
#!/bin/sh
$HADOOP_HOME/bin/hadoop dfs -rmr /rand_$1-sorted
./start_nmon.sh
$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-0.20.1-examples.jar sort
-r 70 /rand_$1
/rand_$1-sorted 2>&1 |tee ./testRes/sort_baseline_$2.out
cp -r /home/hadoop/perf_share ./testRes/nmonFiles/mb$4_$2
|
mapred.tasktracker.map.tasks.maximum
= 2 (默认值) mapred.tasktracker.reduce.tasks.maximum
= 2 (默认值) mapred.reduce.parallel.copies
= 5 (默认值) mapred.child.java.opts
= -Xmx200m (默认值) mapred.job.reduce.input.buffer.percent
= 0 (默认值) io.sort.mb
= 100 (默认值) io.sort.factor
= 10 (默认值) mapred.local.dir
= /hadoop/sdb
dfs.data.dir
= /hadoop/sdc
, /hadoop/sdd
, /hadoop/sde
平均 CPU | 平均内存(活跃) | 平均磁盘 | 平均网络 (KB/s) | ||||
---|---|---|---|---|---|---|---|
磁盘读 (KB/s) | 磁盘写 (KB/s) | 每秒 IO | 读 | 写 | |||
NameNode | 0.10% | 552.43MB | 0.0 | 18.1 | 1.7 | 8.0 | 31.8 |
JobTracker | 0.30% | 822.19MB | 0.0 | 34.1 | 2.0 | 8.8 | 13.0 |
DataNode | 42.5% | 6522.32MB | 49431.2 | 37704.0 | 605.3 | 6134.9 | 7126.4 |
获得所有 nmon 数据之后,可以使用 nmonanalyser 生成图表。因为 nmonanalyser 是一个 Excel 电子表格,所以只需打开它,单击 analyse nmon data,选择 nmon 文件。然后就可以得到经过分析的图表。
nmonanalyser 对于基线测试生成的详细图表如下:
步骤 3:寻找瓶颈
需要根据监视数据和图表仔细地研究系统瓶颈。因为主要的工作负载分配给 DN/TT 节点,所以应该首先观察 DN/TT 节点的资源使用量(下面只给出 DN/TT 节点的 nmon 图表以节省篇幅)。
通过研究基线监视数据和图表,可以发现系统中有几个瓶颈:在 map 阶段,没有充分使用 CPU(大多数时候不到 40%),而且磁盘 I/O 相当频繁。
步骤 4:打破瓶颈
首先尝试提高 map 阶段的 CPU 利用率。前面对 Hadoop 参数的说明指出,要想提高 CPU 利用率,需要增加 mapred.tasktracker.map
和 reduce.tasks.maximum
参数的值。
在测试环境中,每个节点有两个支持并发多线程的 4 核处理器,所以有 16 个可用的位置,可以把这两个参数设置为 7。
为了完成这一修改,需要在 mapred-site.xml
中设置 mapred.tasktracker.map
和 reduce.tasks.maximum
参数,重新启动集群,再次启动 baseline_test.sh
(因为在 mapred-site.xml
文件中进行配置,所以这里不需要修改脚本)。修改后的 mapred-site.xml
如下所示:
<configuration>
<property>
<name>mapred.tasktracker.map.tasks.maximum</name>
<value>7</value>
</property>
<property>
<name>mapred.tasktracker.map.tasks.maximum</name>
<value>7</value>
</property>
</configuration>
|
下面是调优后的测试结果:
平均 CPU | 平均内存(活跃) | 平均磁盘 | 平均网络 (KB/s) | ||||
---|---|---|---|---|---|---|---|
磁盘读 (KB/s) | 磁盘写 (KB/s) | 每秒 IO | 读 | 写 | |||
NameNode | 0.10% | 520.88MB | 0.0 | 21.2 | 2.0 | 6.4 | 12.7 |
JobTracker | 0.50% | 1287.4MB | 0.0 | 22.5 | 1.6 | 6.4 | 5.1 |
DataNode | 48.4% | 12466.8MB | 51729.07 | 44060.67 | 669.9 | 7462 | 6865 |
图 5. 调优后的 DataNode/TaskTracker 图表
步骤 5:新一轮调优,重复步骤 3 和 4
增加每个 TaskTracker 中 map/reduce 任务的最大数量之后,观察获取的数据和图表,可以看到在 map 阶段已经充分使用 CPU 了。但是与此同时,磁盘 I/O 频率仍然很高,所以需要新一轮调优-监视-分析过程。
需要重复这些步骤,直到系统中没有瓶颈,每种资源都充分使用为止。
注意,每次调优不一定会提高性能。如果出现性能下降,需要恢复以前的配置,尝试用其他调优措施打破瓶颈。在这次测试中,最终取得的优化结果如下:
图 6. DataNode/TaskTracker 图表 - 第二轮调优
步骤 6:可伸缩性测试和改进
为了进一步检验调优结果,需要在使用优化后的配置的情况下增加集群规模和输入数据规模,从而测试配置的可伸缩性。具体地说,把集群规模增加到 30 个节点,把输入数据规模增加到 1.5TB,然后再次执行上面的测试过程。
由于篇幅有限,这里不详细描述调优过程。监视和分析方法与上面提到的完全相同,发现的主要瓶颈出现在网络中。当输入数据增加到 TB 量级时,机架间带宽变得不足。把机架间带宽增加到 4 Gb,10 节点集群优化后的所有其他参数保持不变,最终的执行时间是 5916 秒,这相当接近 10 节点集群优化后的结果(5670 秒)。
回页首
结束语
您现在了解了如何监视 Hadoop 集群、使用监视数据分析系统瓶颈和优化性能。希望这些知识能够帮助您充分使用 Hadoop 集群,更高效地完成作业。可以使用本文描述的方法进一步研究 Hadoop 的可配置参数,寻找参数配置与不同作业特征之间的关联。
另外,这种基于参数的调优比较 “静态”,因为一套参数配置只对于一类作业是最优的。为了获得更大的灵活性,您应该研究 Hadoop 的调度算法,寻找提高 Hadoop 性能的新方法。
参考资料
学习