作者:刘旭晖Raymond转载请注明出处
Email:[email protected]
BLOG:http://blog.csdn.net/colorant/
记录一下这几天学习Hadoop的几个测试用例的理解。主要是三个Sort/TeraSort/TestDFSIO, 这几个example一方面可以用来做benchmark,另一方面通过学习阅读,也有助于理解Hadoop的MR框架 ;)
Sort : org.apache.hadoop.examples.Sort
功能目的
Sort的功能就是对输入文件按Key进行排序。默认处理格式为
流程分析
如果不考虑全排序功能的话,Sort本身的实现是相当简单的,Map和Reduce阶段都采用Hadoop自带的IdentityMapper/Reducer,即不对数据做任何处理,直接输出。完全利用Hadoop Framework在Map的output阶段和Reduce阶段的排序功能对key值进行排序
相关思考
如果不使用TotalOrder,Sort的输出结果中,每个Reduce Task的输出是局部排序的,但是各个Reduce Task的输出结果之间是没有经过全局排序过的。这是因为在partition阶段对
TeraSort: org.apache.hadoop.examples.terasort.TeraSort
功能目的
对输入文件按Key进行全局排序。另外TeraSort针对的是大批量的数据,在实现过程中为了保证Reduce阶段各个Reduce Job的负载平衡,以保证全局运算的速度,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就采用了更通用的二分查找法来定位分区)
相关思考
由于Partitioner中将数据按Key值大小归类到不同的分区中,而各个分区内部由Hadoop的框架进行了排序,所以最终得到的结果就是全局排序的结果了
前面Sort.java在做全局排序的时候也使用了类似的方法,不同的是采样和分区定位的方式不同,实现的方式更加通用一些。
为了加快TeraSort数据输出的速度,这个Job的data replica被设置为1
另外,http://blog.csdn.net/leafy1980/article/details/6633828 这里对TeraSort做了更详细的流程介绍
TestDFSIO : org.apache.hadoop.fs.TestDFSIO
功能目的
测试 HDFS的读写速度
流程分析
使用Hadoop MapReduce框架的主要目的是通过多个Map Task模拟多路的并发读写。
TestDFSIO通过实现了自己的Mapper class用来读写数据,生成统计信息,然后实现了自己的Reduce Class来收集并汇总各个Map Task的统计信息,主要涉及到三个文件 : AccumulatingReducer.java, IOMapperBase.java, TestDFSIO.java
程序的大致流程如下:
• 根据Map Task的数量将相应个数的Control控制文件写入HDFS,这些控制文件仅包含一行内容:<数据文件名,数据文件大小>
• 启动MapReduceJob,IOMapperBase Class中的Map方法将Control文件作为输入文件,读取内容,将数据文件名和大小作为参数传递给自定义的doIO函数,进行实际的数据读写工作。而后将数据大小和doIO执行的时间传递给自定义的collectStatus函数,进行统计数据的输出工作
• doIO的实现:TestDFSIO重载并实现doIO函数,将指定大小的数据写入HDFS文件系统。
• collectStatus的实现:TestDFSIO重载并实现collectStatus函数,将任务数量(1),以及数据大小,完成时间等相关数据作为Map Class的结果输出
o 统计数据用不同的前缀标识,例如 l: (stand for long), s: ( stand for string) etc.
• 执行唯一的一个Reduce任务,收集各个Map Class的统计数据,使用AccumulatingReducer进行汇总统计
• 最后当MapReduceJob完成以后,调用analyzeResult函数读取最终的统计数据并输出到控制台和本地的Log文件中
相关思考
可以看到在这个流程中,实际通过MR框架进行读写Shuffle的只是Control文件,数据量非常小,所以MR框架本身的数据传输对测试的影响很小,可以忽略不计,测试结果完全取决于HDFS的读写性能。