如果我的作业输入是文件集[a,b,c,d],则严格排序的输入是[map(a.0),map(a.1),map(b.0) ,地图(b.1),地图(c.0),地图(c.1),地图(d.0),地图(d.1)]?
我的动机是有一系列文件(当然会分成块),其行是[key,value];其中每个键和值都是一个简单的字符串。我希望在每个键的reducer中按照它们在输入中出现的顺序将这些值连接在一起,尽管没有明确的顺序定义字段。
任何建议都非常感谢;这对Google来说是个难题。
输入格式
A First
A Another
A Third
B First
C First
C Another
期望的输出
A First,Another,Third
B First
C First,Another
重申一点,我不确定我是否可以依靠以正确的顺序获得First-Third,因为文件存储在不同的块中。
答案 0 :(得分:0)
不,您无法保证使用Hadoop中的标准数据流(即标准分拣机,分区器,分组器),这些值将按此顺序排列。唯一可以保证的是键的顺序(A,B,C)。
为了达到你想要的效果,你必须编写自己的分拣机,并在key =>中包含值(第一,第二,第三)。新密钥将是:
"A First"
"A Second"
...
但是,在这种情况下的问题是这些密钥将最终出现在不同的分区中(标准的散列分区程序很可能会将“A first”分配给一个分区而“A second”分配给另一个分区)所以,到避免这个问题你也应该插入你自己的分区器,它只使用密钥的第一部分(即A)来进行分区。 你应该定义石斑鱼,否则“A first”,“A second”将不会同时传递给同一个reduce调用。
因此,map函数的输出应为:
"A First" First
"A Second" Second
...
换句话说,映射器输出的值应该按原样使用。否则,您将无法获得reducer中的值。
答案 1 :(得分:0)
此问题的一个解决方案是在文件中使用TextInputFormat的字节偏移量作为复合键的一部分,并使用辅助排序来确保按顺序将值发送到reducer。这样,您可以确保reducer按照文件中的顺序看到您想要的键所分配的输入。如果您有多个输入文件,则此方法将不起作用,因为每个新文件都将重置字节计数器。
使用流API,您需要将-inputformat TextInputFormat -D stream.map.input.ignoreKey=false
传递给作业,以便实际获得字节偏移作为键(by default如果输入格式为,则PipeMapper不会为您提供键TextInputFormat ..即使您显式设置TextInputFormat标志so you need to set the additional ignoreKey flag)。
如果您从映射器发出多个键,请务必设置以下标志,以便输出在第一个键上分区,并在reducer中的第一个和第二个键上排序:
-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"