【发布时间】:2015-02-11 09:35:31
【问题描述】:
所以我使用 MultipleOutputs 包中的 org.apache.hadoop.mapreduce.lib.output。
我有一个 reducer,它正在连接 2 个数据源并发出 3 个不同的输出。
调用了 55 个 reduce 任务,平均每个任务需要大约 6 分钟来发出数据。有异常值大约需要 11 分钟。
所以我观察到,如果我评论实际输出发生的部分,即调用mos.write()(多输出),那么平均时间会减少到几秒钟,整个工作大约在 2 分钟内完成。
我确实有很多数据要发出(大约 40-50 GB)的数据。
在考虑和不考虑压缩的情况下,我可以做些什么来加快速度。
详细信息:我正在使用 TextOutputFormat 并提供 hdfs 路径/uri。
进一步说明:
我的reducer 的输入数据很少,但是reducer 正在执行reduce side join,因此会发出大量数据。由于异常值 reducer 大约需要 11 分钟,因此减少 reducer 的数量会增加这个时间,因此会增加我工作的总时间,并且不会解决我的目的。
reducer 的输入来自 2 个映射器。 映射器 1 -> 发出大约 10,000 条记录。 (密钥 ID) 映射器 2 -> 发出大约 1500 万条记录。 (Key Id, Key Id2, Key Id3)
在 reducer 中,我得到属于 Key Id 的所有内容,按 Key Id、KeyId2 和 KeyId3 排序。
所以我知道我有一个迭代器,它类似于: Mapper1 输出,然后 Mapper2 输出。
在这里,我将 Mapper1 的输出存储在 ArrayList 中并开始流式传输 Mapper2 的输出。
对于我所做的每条 Mapper2 记录,mos.write(....)
我有条件地将这条记录的一部分存储在内存中(在HashSet 中)
每次 KeyId2 更改时,我都会多做一次mos.write(...)
在我的 reducer 的 close 方法中,如果我在条件步骤中存储了任何内容,我会发出。所以第三个mos.write(...)
我已经看过文章http://blog.cloudera.com/blog/2009/12/7-tips-for-improving-mapreduce-performance/ 如前所述:
提示 1:正确配置我的集群超出了我的控制范围。
提示 2:使用 LZO 压缩 - 或一般的压缩。我正在尝试的东西。
提示 3:调整映射器和缩减器的数量 - 我的映射器完成得非常快(以秒为单位)可能是因为它们几乎是身份映射器。如上所述,Reducer 需要一些时间(这是我试图减少的时间)所以增加 reducer 的数量可能会对我有所帮助 - 但随后会出现资源争用,一些 reducer 将不得不等待。对我来说,这更像是一种实验性的尝试和错误。
提示4:编写一个组合器。不适用于我的情况(减少侧连接)
提示5:使用 apt writable - 我现在需要使用 Text。所有这 3 个输出都将进入具有 hive 架构的目录。稍后当我想出如何从多个输出中发出 ParquetFormat 文件时,我可能会更改此方法和表存储方法。
提示6:重用可写文件。好的,这是我到目前为止还没有考虑过的事情,但我仍然相信它的磁盘写入需要时间而不是处理或 java 堆。但无论如何,我会再试一次。
提示7:使用穷人的侧写。有点已经这样做了,并发现它实际上是 mos.write 大部分时间的步骤。
【问题讨论】:
-
尝试仅写入单个输出(例如 context.write() 而不是 mod)以查看 i/o 性能是系统性的还是仅与 mos 的使用有关。
-
您使用的是哪种类型的目的地?最近我遇到了一个关于 nfs 共享的问题,直到它被更新和调整。
-
@ChrisGerken 当然......但我确实需要输出到多个目录。我不认为 context.write 的良好性能对我来说是一个解决方案。
-
@loshadvtapkah 我正在使用标准的 hdfs 目的地。用同样的方法更新了我的问题。还有什么我应该提到的细节吗?
标签: hadoop