首页 文章

深入了解Map中 Map 阶段的内部工作会减少hadoop中的工作吗?

提问于
浏览
6

我正在读汤姆怀特的 Hadoop: The definitive guide 3rd edtition . 它是理解我感兴趣的 Hadoop 内部的优秀资源,尤其是 Map-Reduce .

从书中,(页205):

Shuffle and Sort

MapReduce保证每个reducer的输入按键排序 . 系统执行排序的过程 - 将映射输出作为输入传递给Reducer - 称为shuffle .

我从中推断出,在将键发送到reducer之前,它们被排序,表明作业的map阶段的输出被排序 . 请注意:我不称之为mapper,因为map阶段包括mapper(由程序员编写)和MR框架的内置排序机制 .


The Map Side

每个map任务都有一个循环内存缓冲区,用于将输出写入 . 默认情况下,缓冲区为100 MB,可以通过更改io.sort.mb属性来调整大小 . 当缓冲区的内容达到某个阈值大小(io.sort.spill.per,默认为0.80或80%)时,后台线程将开始将内容溢出到磁盘 . 在溢出发生时, Map 输出将继续写入缓冲区,但如果缓冲区在此期间填满,则 Map 将阻塞,直到溢出完成 .
在写入磁盘之前,线程首先将数据分成 partitions corresponding to the reducers ,它们最终将被发送到 . 在每个分区中,后台线程按键执行内存中排序,如果有组合器函数,则在排序输出上运行 . 运行组合器功能可以实现更紧凑的映射输出,因此可以将更少的数据写入本地磁盘并传输到reducer .

我对上一段的理解是,当映射器生成键值对时,键值对被分区和排序 . 一个假设的例子:

考虑使用mapper-1进行字数统计:

>mapper-1 contents
partition-1
   xxxx: 2
   yyyy: 3
partition-2
   aaaa: 15
   zzzz: 11

(请注意每个分区数据按键排序,但分区-1的数据和分区2的数据不必按顺序排序)


Continuing reading the chapter:

每次内存缓冲区达到溢出阈值时,都会创建一个新的溢出文件,因此在映射任务写入其最后一个输出记录后,可能会有多个溢出文件 . 在任务完成之前,溢出文件将合并到 single partitioned and sorted output file 中 . 配置属性io.sort.factor一次控制要合并的最大流数;默认值为10 .

我的理解是(请知道上面的段落中的粗体短语,欺骗了我):在map-task中,有几个文件可能会溢出到磁盘,但它们会合并到一个仍然包含分区并进行排序的文件中 . 考虑与上面相同的例子:

在单个map-task完成之前,其中间数据可以是:

mapper-1内容

spill 1:             spill 2:           spill 2:
    partition-1         partition-1        partition-1
                          hhhh:5       
       xxxx: 2            xxxx: 3             mmmm: 2
       yyyy: 3            yyyy: 7             yyyy: 9 

    partition-2         partition-2        partition-2
       aaaa: 15           bbbb: 15            cccc: 15
       zzzz: 10           zzzz: 15            zzzz: 13

map-task完成后,mapper的输出将是一个文件(注意上面添加了三个溢出文件,但假设在job conf中没有指定组合器,则不应用合成器):

>Mapper-1 contents:
partition-1:
hhhh: 5
mmmm: 2
xxxx: 2
xxxx: 3
yyyy: 3
yyyy: 7
yyyy: 9
partition-2:
aaaa: 15
bbbb: 15
cccc: 15
zzzz: 10
zzzz: 15
zzzz: 13

所以这里partition-1可能对应reducer-1 . 即上面对应的parition-1段的数据被发送到reducer-1,对应于partition-2段的数据被发送到reducer-2 .

如果到目前为止,我的理解是正确的,

  • 如何从mapper输出中获取包含分区和排序数据的中间文件 .

  • 有趣的是,单独运行映射器不会产生与发送到reducer的数据未排序的点相矛盾的排序输出 . More details here

  • 如果不运行Mapper,甚至不应用任何组合器:More details here

1 回答

  • 8

    仅限 Map 的作业与Map-and-Reduce作业的工作方式不同 . 它并不矛盾,只是不同 .

    我将如何从mapper输出中获取包含分区和排序数据的中间文件 .

    你不能 . 没有一个钩子能够从MapReduce的中间阶段获取数据 . 在分区之后或在记录阅读器之后获取数据也是如此 .

    有趣的是,单独运行映射器不会产生与发送到reducer的数据未排序的点相矛盾的排序输出 . 更多细节在这里

    它并不矛盾 . 映射器排序是因为reducer需要对其进行排序以便能够进行合并 . 如果没有减速器,则没有理由进行排序,因此没有 . 这是正确的行为,因为我不希望它在 Map 中排序只有让我的处理速度变慢的工作 . 我从未遇到过我希望我的 Map 输出在本地排序的情况 .

    如果只运行Mapper,即使没有应用组合器:此处有更多详细信息

    组合器是一种优化 . 无法保证它们实际运行或通过什么数据 . 组合器主要用于使减速器更有效 . 所以,再次,就像本地排序一样,如果没有减速器,组合器就不会运行,因为它没有理由 .

    如果你想要类似于组合器的行为,我建议将数据写入缓冲区(可能是hashmap),然后在Mapper完成时运行的清理函数中写出本地汇总的数据 . 如果要执行此操作,请注意内存使用情况 . 这是一种更好的方法,因为组合器被指定为一个有益的优化,你不能指望它们运行......即使它们确实运行 .

相关问题