2

如果我的工作的输入是文件集 [a, b, c, d],那么严格排序的输入是 [map(a.0), map(a.1), map(b.0), map( b.1)、地图(c.0)、地图(c.1)、地图(d.0)、地图(d.1)]?

我的动机是拥有一系列文件(当然会被分成块),其行是 [key, value]; 其中每个键和值都是一个简单的字符串。尽管没有明确的顺序定义字段,但我希望按照它们在输入中出现的顺序在每个键的 reducer 中将这些值连接在一起。

非常感谢任何建议;事实证明,这对谷歌来说是一个困难的查询。

例子

输入格式

A First
A Another
A Third
B First
C First
C Another

期望的输出

A First,Another,Third
B First
C First,Another

重申一下,鉴于文件存储在单独的块中,我不确定是否可以依靠正确的顺序获得 First-Third。

4

2 回答 2

0

解决此问题的一种方法是使用文件中 TextInputFormat 的字节偏移量作为复合键的一部分,并使用辅助排序来确保将值按顺序发送到 reducer。这样,您可以确保减速器看到输入按您想要的键按照它在文件中出现的顺序进行分区。如果您有多个输入文件,那么这种方法将不起作用,因为每个新文件都会重置字节计数器。

使用流式 API,您需要将其传递-inputformat TextInputFormat -D stream.map.input.ignoreKey=false给作业,以便您实际上将字节偏移量作为键(默认情况下,如果 inputformat 是 TextInputFormat,PipeMapper 不会给您键。即使您明确设置了 TextInputFormat 标志所以你需要设置额外的 ignoreKey 标志)。

如果您从映射器发出多个键,请确保设置以下标志,以便您的输出在第一个键上进行分区,并在减速器中的第一个和第二个键上排序:

-partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner
-D stream.num.map.output.key.fields=2
-D mapred.text.key.partitioner.options="-k1,1"
-D mapred.output.key.comparator.class="org.apache.hadoop.mapred.lib.KeyFieldBasedComparator"
-D mapreduce.partition.keycomparator.options="-k1 -k2n"
于 2012-07-13T16:15:41.593 回答
0

不,您无法保证使用 Hadoop 中的标准数据流(即标准排序器、分区器、分组器)时这些值将按该顺序排列。唯一可以保证的是键的顺序(A、B、C)。

为了实现您想要的,您必须编写自己的排序器并在键中包含值(第一、第二、第三)=> 新键将是:

  "A First"
  "A Second"
  ...

但是,在这种情况下,问题是这些键最终会出现在不同的分区中(标准哈希分区器很可能会将“A first”分配给一个分区,将“A second”分配给另一个分区)所以,为了避免这个问题您还应该插入您自己的分区程序,它将仅使用密钥的第一部分(即 A)来进行分区。您还应该定义分组器,否则“A first”、“A second”将不会一起传递给同一个 reduce 调用。

所以你的地图功能的输出应该是:

 "A First"    First
 "A Second"   Second
 ...

换句话说,映射器输出的值应该保持原样。否则你将无法获得减速器中的值。

于 2012-07-13T10:22:39.280 回答