Hadoop的shuffle过程就是从map端输出到reduce端输入之间的过程,这一段应该是Hadoop中最核心的部分,因为涉及到Hadoop中最珍贵的网络资源,所以shuffle过程中会有很多可以调节的参数,也有很多策略可以研究。这里没有对shuffle做深入的分析,也没有读源代码,只是根据资料和使用的一些理解。
map端
map过程的输出是写入本地磁盘而不是HDFS,但是一开始数据并不是直接写入磁盘而是缓冲在内存中,缓存的好处就是减少磁盘I/O的开销,提高合并和排序的速度。默认的内存缓冲大小是100M(可以配置),所以在书写map函数的时候要尽量减少内存的使用,为shuffle过程预留更多的内存,因为该过程是最耗时的过程。
当缓冲的内存大小使用超过一定的阈值(默认80%),一个后台的线程就会启动把缓冲区中的数据写入(spill)到磁盘中,往内存中写入的线程继续写入知道缓冲区满,缓冲区满后线程阻塞直至缓冲区被清空。
在数据spill到磁盘的过程中会有一些额外的处理,调用partition函数、combine函数(如果设置)、对数据进行排序(按key排序)。如果发生多次磁盘的溢出写,会在磁盘上形成几个溢出写文件,在map过程结束时,要将这些文件进行合并生成一个大的分区的排序的文件(比较绕)。
另外在写磁盘的时候才用压缩的方式将map的输出结果进行压缩是减少网络开销很有效的方法,对压缩了解不错,就不写了。
reduce端
reduce端可能从n多map的结果中获取数据,而这些map的执行速度不尽相同,当其中一个map运行结束时,reduce就会从jobtractor中获取该信息。map运行结束后tasktractor会得到消息,进而将消息汇报给jobtractor,reduce定时从jobtractor获取该信息,reduce端默认有5个线程从map端拖拉数据。
同样从map端拖来的数据(pull)先写到reduce端的缓存中,同样缓存占用到达一定阈值后会将数据写到磁盘中,同样会进行partition、combine、排序等过程。如果形成多个磁盘文件还会进行合并最后一次合并的结果作为reduce的输入而不是写入到磁盘中。
reduce的结果将会写入到HDFS,如果执行任务的节点也是HDFS的一个节点,本地会保存一个副本。