3、TeraSort的原理
了解了我们需要排序的输入数据是什么样了,接下来来了解TeraSort。
运行TeraSort的命令是这样的:
$ bin/hadoop jar hadoop-0.19.2-examples.jar terasort /terasort/input1TB /terasort/output1TB |
运行后,我们可以看到会起m个mapper(取决于输入文件个数)和r个reducer(取决于设置项:mapred.reduce.tasks),排好序的结果存放在/terasort/output1TB目录。
查看TeraSort的源代码,你会发现这个作业同时没有设置mapper和reducer;也就是意味着它使用了Hadoop默认的IdentityMapper和IdentityReducer。IdentityMapper和IdentityReducer对它们的输入不做任何处理,将输入k,v直接输出;也就是说是完全是为了走框架的流程而空跑。
这正是Hadoop的TeraSort的巧妙所在,它没有为排序而实现自己的mapper和reducer,而是完全利用Hadoop的Map Reduce框架内的机制实现了排序。
我们需要先来了解下Hadoop的Map Reduce过程,下图较清楚的说明了这个过程。
(这个图非常经典,截自:Hadoop:The Definitive Guide)
恰好趁这个机会,把自己对MapReduce过程的理解简要的整理一下:
● 一般情况下,作业会需要指定input目录和output目录
● 作业的Mapper根据设置的InputFormat来从input目录读取输入数据,分成多个splits; 每一个split交给一个mapper处理
● mapper的输出会按照partions分组,每一个partion对应着一个reducer的输入; 在每个partion内,会有一个按key排序的过程,也就是说,每一个partion内的数据是有序的。
● 当处理完combiner和压缩后(如果有设置),map的输出会写到硬盘上。map结束后,所在的TT会在下一个心跳通知到JT。
● 每一个reducer查询JT了解到属于自己对应partition的mapoutput数据的对应的TT位置,然后去那copy到本地(HTTP协议)。
● Copy并保存到本地磁盘的过程同mapper端的输出保存过程非常相似。等到reducer获取到属于它的所有mapoutput数据后,它会保持之前mapper端的sort顺序,把这些mapoutput合并成较集中的中间文件(个数取决于数据大小和设置)。为了节省io的开销,merge会保证最后一轮是满负荷合并;并且,merge的最后一轮输出会直接在内存输入给reducer。
● reducer的输出按照OutputFormat来保存到output目录。
如果我们注意到上述过程的蓝色加粗部分,就可以猜测到TeraSort是如何利用hadoop的map reduce机制来达到排序目的的。或许我们可以怀疑,hadoop的Map Reduce机制就是为了TeraSort而设计的,:) 。
既然Hadoop可以保证每一个partition内的数据有序,TeraSort只需要做一件事情:保证partition之间也是有序的。