1

我正在 Hadoop 中编写一个 Reducer,我正在使用它的输入值来构建一个对元素列表进行编码的字节数组。我在其中写入数据的缓冲区的大小取决于减速器接收到的值的数量。提前在内存中分配它的大小会很有效,但是如果不使用“foreach”语句对它们进行迭代,我不知道有多少值。

Hadoop 输出是一个 HBase 表。

更新: 使用映射器处理我的数据后,reducer 键具有幂律分布。这意味着只有少数几个键有很多值(最多 9000),但大多数只有几个值。我注意到通过分配一个 4096 字节的缓冲区,97.73% 的值适合它。对于其余的人,我可以尝试重新分配具有双倍容量的缓冲区,直到所有值都适合它。对于我的测试用例,这可以通过在最坏的情况下重新分配内存 6 次来完成,即一个键有 9000 个值。

4

2 回答 2

2

我假设您将在分配字节数组之后使用 for-each 来遍历它们,但是您不希望必须缓冲内存中的所有记录(因为您只能循环遍历您的迭代器从您的价值收集中取回一次)。因此,您可以

  1. 运行一个计数归约器,输出每个输入记录,并将计数输出到与映射输出具有相同值类的记录,然后使用自定义排序对该结果运行“仅归约”作业,以放置计数第一个(推荐)
  2. 覆盖您使用 Hadoop 获得的内置排序以在排序时计数并将该计数记录作为其输出的第一条记录注入(我并不完全清楚您将如何完成覆盖,但一切皆有可能)
  3. 如果这些值是唯一的,您可能能够拥有一个有状态的排序比较器,它保留了它被调用的值的哈希值(这看起来非常h​​acky且容易出错,但我敢打赌,如果机制二级排序仅限于一个 JVM 中的一个类加载器)
  4. 设计你的 reducer 以使用比字节数组更灵活的数据结构,并在必要时在输出之前将结果转换为字节数组(强烈推荐)
于 2012-08-04T05:25:22.750 回答
0

您可以使用以下范例:

Map:每个映射器都保存一个从键到整数的映射,其中 M[k] 是使用某个键 k 发出的值的数量。在其输入结束时,映射还将发出键值对 (k, M[k])。

排序:使用二级排序,使对 (k, M[k]) 出现在对 (k, your values) 之前。

减少:假设我们正在查看密钥 k。然后reducer首先聚合来自不同映射器的计数M[k]以获得一个数字n。这是您要查找的号码。现在您可以创建数据结构并进行计算。

于 2013-08-18T01:21:07.877 回答