java - 在 Hadoop Map-Reduce 中,是否有任何类在排序之后和分区之前看到整个键列表?

标签 java hadoop mapreduce partitioning partitioner

我正在使用 Hadoop 分析分布非常不均匀的数据。有些键有数千个值,但大多数只有一个。例如,与 IP 地址相关联的网络流量会有许多数据包与一些多话的 IP 相关联,而只有少数数据包与大多数 IP 相关联。另一种说法是 Gini index非常高。

为了有效地处理这个问题,每个 reducer 应该获得一些高容量键或大量低容量键,以便获得大致均匀的负载。如果我正在编写分区过程,我知道我将如何做到这一点:我将采用 keys 的排序列表。 (包括所有重复键)由映射器生成以及缩减器的数量 N并把拆分放在

split[i] = keys[floor(i*len(keys)/N)]

reducer i会得到 key k这样 split[i] <= k < split[i+1]对于 0 <= i < N-1split[i] <= k对于 i == N-1 .

我愿意用 Java 编写自己的分区程序,但是 Partitioner<KEY,VALUE>类似乎一次只能访问一个键值记录,而不是整个列表。我知道 Hadoop 对映射器生成的记录进行排序,所以这个列表一定存在于某个地方。它可能分布在多个分区器节点中,在这种情况下,我会在其中一个子列表上执行拆分过程,并以某种方式将结果传达给所有其他分区器节点。 (假设所选的分区器节点看到一个随机子集,结果仍然大致是负载平衡的。)有谁知道排序的键列表存储在哪里,以及如何访问它?

我不想编写两个 map-reduce 作业,一个用于查找拆分,另一个用于实际使用它们,因为这看起来很浪费。 (映射器必须做两次相同的工作。)这似乎是一个普遍的问题:分布不均很常见。

最佳答案

我也一直在思考这个问题。如果有人强制我,这是我会采取的高级方法。

  • 除了用于解决业务问题的映射器逻辑之外,还可以编写一些逻辑来收集分区程序中需要的任何统计信息,从而以平衡的方式分发键值对。当然,每个映射器只会看到部分数据。
  • 每个映射器都可以找到它的任务 ID,并使用该 ID 在指定的 hdfs 文件夹中构建一个唯一的文件名,以保存收集到的统计信息。在任务结束时运行的 cleanup() 方法中写出此文件。
  • 在分区程序中使用惰性初始化来读取指定的 hdfs 目录中的所有文件。这将为您提供在映射器阶段收集的所有统计信息。从那里开始,您需要实现正确分区数据所需的任何分区逻辑。

这一切都假设在所有映射器完成之前不会调用分区器,但这是迄今为止我能做的最好的事情。

关于java - 在 Hadoop Map-Reduce 中,是否有任何类在排序之后和分区之前看到整个键列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12117088/

相关文章:

java - JComponent 不可见,有人知道为什么吗?

java - Java 满足条件后停止循环

java - 如何调用以接口(interface)为参数的方法?

hadoop - 查找杀死 Hadoop 作业的用户名

java - 使用java读取HDFS中的文件并通过regex匹配多行 block

hadoop - Hadoop 在 N 层架构中的什么位置?

eclipse - "Not A Valid Jar"尝试运行 Map Reduce 作业时

java - 使用 JavaFX 缩放窗口时自动将程序内容居中

oracle - 如何将hadoop数据存储到oracle中

hadoop - 将参数 "args"从主类传递给 Map 类