【问题标题】:In-depth understanding of internal working of map phase in a Map reduce job in hadoop?深入了解hadoop中Map reduce作业中map阶段的内部工作?
【发布时间】:2014-07-23 18:13:03
【问题描述】:

我正在阅读 Tom White 的 Hadoop: The definitive guide 3rd edtition。这是了解Hadoop 内部结构的绝佳资源,尤其是我感兴趣的Map-Reduce

从书中,(第205页):

随机和排序

MapReduce 保证每个 reducer 的输入都是按键排序的。系统执行排序并将 map 输出作为输入传输到 reducer 的过程称为 shuffle。

由此推断,key在发送到reducer之前是先排序的,说明job的map阶段的输出是排序的。请注意:我不叫它mapper,因为map阶段包括mapper(程序员编写)和MR框架的内置排序机制。


地图一侧

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

我对上一段的理解是,在mapper产生key-value对的时候,key-value对是被分区和排序的。一个假设的例子:

考虑将 mapper-1 用于字数统计程序:

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

(注意with-in每个partition的数据都是key排序的,但是partition-1和partition-2的数据不一定要按顺序排列)


继续阅读本章:

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

我的理解是(请知道上面段落中的粗体词,它欺骗了我): 在一个映射任务中,多个文件可能会溢出到磁盘,但它们会合并到一个仍然包含分区并已排序的文件中。考虑与上面相同的示例:

在单个地图任务完成之前,它的中间数据可能是:

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 的输出将是一个文件(注意现在添加了上面的三个溢出文件,但假设作业 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。即上面partition-1段对应的数据发送到reducer-1,partition-2段对应的数据发送到reducer-2。

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

  1. 如何从映射器输出中获取包含分区和排序数据的中间文件。
  2. 有趣的是,单独运行 mapper 不会产生排序输出 与数据发送到reducer的点相矛盾的是没有排序的。 More details here
  3. 如果没有只运行 Mapper,即使没有应用组合器:More details here

【问题讨论】:

  • 好问题和好答案!

标签: sorting hadoop mapreduce hadoop2


【解决方案1】:

仅 Map 作业与 Map-and-Reduce 作业的工作方式不同。这不是不一致,只是不同。

如何从映射器输出中获取包含分区和排序数据的中间文件。

你不能。没有钩子可以从 MapReduce 的中间阶段获取数据片段。在分区器之后或在记录读取器之后获取数据等也是如此。

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

这并不矛盾。 Mappers 排序是因为 reducer 需要对它进行排序才能进行合并。如果没有减速器,它就没有理由进行排序,所以它没有。这是正确的行为,因为我不希望它在仅地图作业中排序,这会使我的处理速度变慢。我从来没有遇到过我希望我的地图输出在本地排序的情况。

如果 No only Mapper 运行,即使没有应用组合器:更多细节在这里

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

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

【讨论】:

  • 感谢您提供详细信息。我对数据在 Map 端如何分区和排序的理解是否正确?在溢出文件级别和合并文件。这就是我上图中的假设中间数据..
  • 是的,在地图端进行了分区和排序。 Reducers 通过合并排序的分区文件进行最终的“排序”。
  • 还有一点:如果我有需要单独排序的记录,我无法仅使用映射器来实现这一点。我需要运行一个“虚拟”减速器,它只会吐出传入的数据..
  • 啊,我刚刚注意到您是 MapReduce 设计模式书的作者。天哪,这是一个很棒的资源,我刚刚完成了它的第一章。
  • 你可以只使用映射器来实现这一点——这只是一个黑客攻击和危险的记忆方式。在 setup 函数中创建一个空列表。在 map 函数中附加到该列表。在清理函数中对其进行排序,然后在清理(而不是映射)中执行 context.write。很高兴你喜欢这本书:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 2012-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多