Hadoop 集群基准测试
生产环境中,如何对 Hadoop 集群进行 Benchmark Test?如何进行服务所需的机器选型?如何快速对比出不同集群的性能?
本文将通过 Hadoop 自带的 Benchmark 测试程序:TestDFSIO 和 TeraSort,简单介绍如何进行 Hadoop 的读写 & 计算性能的压测。
回顾上篇文章: 认识多队列网卡中断绑定
(本文使用 2.6.0 的 hadoop 版本进行测试,基准测试被打包在测试程序 JAR 文件中,通过无参调用 bin/hadoop jar ./share/hadoop/mapreduce/xxx.jar 可以得到其列表 )
使用 TestDFSIO
进行集群的 I/O 性能测试处
TestDFSIO :
org.apache.hadoop.fs.TestDFSIO
TestDFSIO 程序原理:
使用多个 Map Task 模拟多路的并发读写。通过自己的 Mapper class 用来读写数据,生成统计信息;通过自己的 Reduce Class 来收集并汇总各个 Map Task 的统计信息,主要涉及到三个文件: AccumulatingReducer.java, IOMapperBase.java, TestDFSIO.java。
TestDFSIO 大致运行过程:
-
根据 Map Task 的数量将相应个数的 Control 控制文件写入 HDFS,这些控制文件仅包含一行内容:<数据文件名,数据文件大小> ;
-
启动 MapReduceJob,IOMapperBase Class 中的 Map 方法将 Control 文件作为输入文件,读取内容,将数据文件名和大小作为参数传递给自定义的 doIO 函数,进行实际的数据读写工作。而后将数据大小和 doIO 执行的时间传递给自定义的 collectStatus 函数,进行统计数据的输出工作 ;
-
doIO 的实现:TestDFSIO 重载并实现 doIO 函数,将指定大小的数据写入 HDFS 文件系统;
-
collectStatus 的实现:TestDFSIO 重载并实现 collectStatus 函数,将任务数量,以及数据大小,完成时间等相关数据作为 Map Class 的结果输出;
-
统计数据用不同的前缀标识,例如 l: (stand for long), s: (stand for string) etc;
-
执行唯一的一个 Reduce 任务,收集各个 Map Class 的统计数据,使用 AccumulatingReducer 进行汇总统计;
-
最后当 MapReduceJob 完成以后,调用 analyzeResult 函数读取最终的统计数据并输出到控制台和本地的 Log 文件中;
那么 MR 任务测试集群读写性能是否会因为数据传输影响到结果判断呢?
可以看整个过程中,实际通过 MR 框架进行读写 Shuffle 的只是 Control 文件,数据量非常小,所以 MR 框架本身的数据传输对测试的影响很小,可以忽略不计,测试结果基本是取决于 HDFS 的读写性能的。
了解到原理后,我们将运行 TestDFSIO 进行测试
测试集群版本:hadoop-2.6.0-mdh3.11
测试集群的机器情况:5 个 slave(dn/nm) 节点,每个节点机器为 32 核,128g 内存,12*4THdd 磁盘的物理机。
测试数据:5 个文件,每个文件大小为 1TB。
环境要求:集群保证完全空闲,无其他干扰任务。
1. 写测试:
bin/hadoop jar ./share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.6.0-mdh3.11-jre8-SNAPSHOT.jar TestDFSIO -write -nrFiles 5 -size 1TB
# 查看测试结果
cat TestDFSIO_results.log
----- TestDFSIO ----- : write
Date & time: Mon Jun 04 16:44:25 CST 2018
Number of files: 5
Total MBytes processed: 5242880.0
Throughput mb/sec: 213.10459447844454
Average IO rate mb/sec: 213.11135864257812
IO rate std deviation: 1.1965074234796487
Test exec time sec: 4972.91
2. 读测试:
bin/hadoop jar ./share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.6.0-mdh3.11-jre8-SNAPSHOT.jar TestDFSIO -read -nrFiles 5 -size 1TB
# 查看测试结果
cat TestDFSIO_results.log
----- TestDFSIO ----- : read
Date & time: Mon Jun 04 18:48:48 CST 2018
Number of files: 5
Total MBytes processed: 5242880.0
Throughput mb/sec: 164.327389903222
Average IO rate mb/sec: 164.33087158203125
IO rate std deviation: 0.7560928117328837
Test exec time sec: 6436.246
以上测试数据解释:
Throughput mb/sec 和 Average IO rate mb/sec 是两个最重要的性能衡量指标:Throughput mb/sec 衡量每个 map task 的平均吞吐量,Average IO rate mb/sec 衡量每个文件的平均 IO 速度。
IO rate std deviation:标准差,高标准差表示数据散布在一个大的值域中,这可能意味着群集中某个节点存在性能相关的问题,这可能和硬件或软件有关。
使用 TeraSort
进行集群的计算性能测试
TeraSort: org.apache.hadoop.examples.terasort.TeraSort
TeraSort 程序原理:
对输入文件按 Key 进行全局排序。TeraSort 针对的是大批量的数据,在实现过程中为了保证 Reduce 阶段各个 Reduce Job 的负载平衡,以保证全局运算的速度,TeraSort 对数据进行了预采样分析。
TeraSort 大致运行过程:
从 job 框架上看,为了保证 Reduce 阶段的负载平衡,使用 jobConf.setPartitionerClass 自定义了 Partitioner Class 用来对数据进行分区,在 map 和 reduce 阶段对数据不做额外处理。Job 流程如下:
-
对数据进行分段采样:例如将输入文件最多分割为 10 段,每段读取最多 100,000 行数据作为样本,统计各个 Key 值出现的频率并对 Key 值使用内建的 QuickSort 进行快速排序(这一步是 JobClient 在单个节点上执行的,采样的运算量不能太大);
-
将样本统计结果中位于样本统计平均分段处的 Key 值(例如 n/10 处 n=[1..10])做为分区的依据以 DistributedCache 的方式写入文件,这样在 MapReduce 阶段的各个节点都能够 Access 这个文件。如果全局数据的 Key 值分布与样本类似的话,这也就代表了全局数据的平均分区的位置;
-
在 MapReduceJob 执行过程中,自定义的 Partitioner 会读取这个样本统计文件,根据分区边界 Key 值创建一个两级的索引树用来快速定位特定 Key 值对应的分区(这个两级索引树是根据 TeraSort 规定的输入数据的特点定制的,对普通数据不一定具有普遍适用性,比如 Hadoop 内置的 TotalPartitioner 就采用了更通用的二分查找法来定位分区);
总结:
TeraSort 使用了 Hadoop 默认的 IdentityMapper 和 IdentityReducer。IdentityMapper 和 IdentityReducer 对它们的输入不做任何处理,将输入 k,v 直接输出;也就是说是完全是为了走框架的流程而空跑。这正是 Hadoop 的 TeraSort 的巧妙所在,它没有为排序而实现自己的 mapper 和 reducer,而是完全利用 Hadoop 的 Map Reduce 框架内的机制实现了排序。 而也正因为如此,我们可以在集群上利用 TeraSort 来测试 Hadoop。
了解到原理后,我们将运行 TeraSort 进行测试
测试集群版本:hadoop-2.6.0-mdh3.11
测试集群的机器情况:
5 个 slave(dn/nm) 节点,每个节点机器为 32 核,128g 内存,12*4THdd 磁盘的物理机。
测试数据:
hadoop 自带的生成数据工具 TeraGen,输入文件是由一行行 100 字节的记录组成,每行记录包括一个 10 字节的 Key;以 Key 来对记录排序。
环境要求:
集群保证完全空闲,无其他干扰任务。
1
测试数据生成
按照 SortBenchmark 要求的输入数据规则(需要 gensort 工具生成输入数据):输入文件是由一行行 100 字节的记录组成,每行记录包括一个 10 字节的 Key;以 Key 来对记录排序。(具体可参考 http://www.ordinal.com/gensort.html)
Hadoop 的 TeraSort 实现的生成数据工具 TeraGen,算法与 gensort 一致,我们将使用 TeraGen 生成测试数据:
(测试数据量为 1T,由于 100 字节一行,则设定行数为 10000000000)
bin/hadoop jar ./share/hadoop/mapreduce/hadoop-mapreduce-examples-2.6.0-mdh3.11-jre8-SNAPSHOT.jar teragen 10000000000 /terasort/input1TB
File System Counters
FILE: Number of bytes read=0
FILE: Number of bytes written=248548
FILE: Number of read operations=0
FILE: Number of large read operations=0
FILE: Number of write operations=0
HDFS: Number of bytes read=173
HDFS: Number of bytes written=1000000000000
HDFS: Number of read operations=8
HDFS: Number of large read operations=0
HDFS: Number of write operations=4
Job Counters
Launched map tasks=2
Other local map tasks=2
Total time spent by all maps in occupied slots (ms)=32792925
Total time spent by all reduces in occupied slots (ms)=0
Total time spent by all map tasks (ms)=10930975
Total vcore-seconds taken by all map tasks=10930975
Total megabyte-seconds taken by all map tasks=8394988800
Map-Reduce Framework
Map input records=10000000000
Map output records=10000000000
Input split bytes=173
Spilled Records=0
Failed Shuffles=0
Merged Map outputs=0
GC time elapsed (ms)=193112
CPU time spent (ms)=14325820
Physical memory (bytes) snapshot=916639744
Virtual memory (bytes) snapshot=12308406272
Total committed heap usage (bytes)=712507392
HeapUsageGroup
HeapUsageCounter=30947608
org.apache.hadoop.examples.terasort.TeraGen$Counters
CHECKSUM=3028416809717741100
File Input Format Counters
Bytes Read=0
File Output Format Counters
Bytes Written=1000000000000
# 查看生成的数据 bin/hadoop dfs -ls /terasort/input1TB
Found 3 items
-rw-r--r-- 3 hdfs_admin supergroup 0 2018-06-05 11:49 /terasort/input1TB/_SUCCESS
-rw-r--r-- 3 hdfs_admin supergroup 500000000000 2018-06-05 11:45 /terasort/input1TB/part-m-00000
-rw-r--r-- 3 hdfs_admin supergroup 500000000000 2018-06-05 11:49 /terasort/input1TB/part-m-00001
2
运行 TeraSort 测试程序
测试数据生成好后,我们将 运行 TeraSort 测试程序:
bin/hadoop jar ./share/hadoop/mapreduce/hadoop-mapreduce-examples-2.6.0-mdh3.11-jre8-SNAPSHOT.jar terasort /terasort/input1TB /terasort/output1TB
18/06/06 03:50:08 INFO mapreduce.Job: Counters: 52
File System Counters
FILE: Number of bytes read=5189229479006
FILE: Number of bytes written=6238290771828
FILE: Number of read operations=0
FILE: Number of large read operations=0
FILE: Number of write operations=0
HDFS: Number of bytes read=1000000856980
HDFS: Number of bytes written=1000000000000
HDFS: Number of read operations=22359
HDFS: Number of large read operations=0
HDFS: Number of write operations=2
Job Counters
Killed map tasks=1
Launched map tasks=7453
Launched reduce tasks=1
Data-local map tasks=4424
Rack-local map tasks=3029
Total time spent by all maps in occupied slots (ms)=356530188
Total time spent by all reduces in occupied slots (ms)=224698152
Total time spent by all map tasks (ms)=118843396
Total time spent by all reduce tasks (ms)=56174538
Total vcore-seconds taken by all map tasks=118843396
Total vcore-seconds taken by all reduce tasks=56174538
Total megabyte-seconds taken by all map tasks=91271728128
Total megabyte-seconds taken by all reduce tasks=57522726912
Map-Reduce Framework
Map input records=10000000000
Map output records=10000000000
Map output bytes=1020000000000
Map output materialized bytes=1040000044712
Input split bytes=856980
Combine input records=0
Combine output records=0
Reduce input groups=10000000000
Reduce shuffle bytes=1040000044712
Reduce input records=10000000000
Reduce output records=10000000000
Spilled Records=59896435961
Shuffled Maps =7452
Failed Shuffles=0
Merged Map outputs=7452
GC time elapsed (ms)=14193819
CPU time spent (ms)=179564830
Physical memory (bytes) snapshot=3104994074624
Virtual memory (bytes) snapshot=46362045841408
Total committed heap usage (bytes)=2586227769344
HeapUsageGroup
HeapUsageCounter=896956972576
Shuffle Errors
BAD_ID=0
CONNECTION=0
IO_ERROR=0
WRONG_LENGTH=0
WRONG_MAP=0
WRONG_REDUCE=0
File Input Format Counters
Bytes Read=1000000000000
File Output Format Counters
Bytes Written=1000000000000
18/06/06 03:50:08 INFO terasort.TeraSort: done
# 查看输出 bin/hadoop dfs -ls /terasort/output1TB
Found 3 items
-rw-r--r-- 1 hdfs_admin supergroup 0 2018-06-06 03:50 /terasort/output1TB/_SUCCESS
-rw-r--r-- 10 hdfs_admin supergroup 0 2018-06-05 11:52 /terasort/output1TB/_partition.lst
-rw-r--r-- 1 hdfs_admin supergroup 1000000000000 2018-06-06 03:50 /terasort/output1TB/part-r-00000
通过 Job Counters 等指标我们可以看出整个 TeraSort 的运行情况,可以通过这些数据对比出当前框架的计算性能。
3
结果的校验:TeraValidate
TeraSort 自带校验程序 TeraValidate,用来检验排序输出结果是否是有序的:
bin/hadoop jar ./share/hadoop/mapreduce/hadoop-mapreduce-examples-2.6.0-mdh3.11-jre8-SNAPSHOT.jar teravalidate /terasort/output1TB /terasort/validate1TB
如果有错误,log 记录会放在输出目录里。
总结
Hadoop 自带的 Benchmark 测试程序看起来微不足道,如果我们能够多多挖掘,便可发挥更大的价值;既可以用来对集群上线前的测试校验,又可以用来进行集群调优测试,通过举一反三可以用到更多地地方。
参考文献
《Hadoop 权威指南》
Benchmarking and Stress Testing an Hadoop Cluster with TeraSort, TestDFSIO & Co.