Hadoop MR2:具有相同密钥的记录是独立处理的

时间:2014-12-03 10:07:22

标签: hadoop mapreduce

我有以下设置:映射器输出密钥类型为K1且值类型为V1K1WritableComparable的记录。因此,组合器获得K1Iterable<V1>作为其输入。然后它进行聚合并输出一个K1, V1记录。 reducer从组合器获取输入,再次为K1, Iterable<V1>。据我所知,在Reduce阶段,每个人K1, Iterable<V1>必须只有一个K1对。然后减速器只输出一个K2, V2K2再次WritableComparable

我现在的问题是:我的输出文件中有多个K2, V2,即使在同一个文件中也是如此!我的关键类的比较方法是正确的,我仔细检查了它。这里出了什么问题?我是否还必须实现equals和hashCode?我认为通过比较和检查比较结果是否为0来执行相等。

还是有其他我遗忘的东西吗?

以下是关键实施:

可写密钥继承自:

package somepackage;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import org.apache.hadoop.io.Writable;

public class SomeWritable implements Writable {

        private String _string1;
        private String _string2;

        public SomeWritable() {
                super();
        }

        public String getString1() {
                return _string1;
        }

        public void setString1(final String string1) {
                _string1 = string1;
        }

        public String getString2() {
                return _string2;
        }

        public void setString2(final String string2) {
                _string2 = string2;
        }

        @Override
        public void write(final DataOutput out) throws IOException {
                out.writeUTF(_string1);
                out.writeUTF(_string2);
        }

        @Override
        public void readFields(final DataInput in) throws IOException {
                _string1 = in.readUTF();
                _string2 = in.readUTF();
        }
}

我使用的密钥:

package somepackage;

import static org.apache.commons.lang.ObjectUtils.compare;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import org.apache.hadoop.io.WritableComparable;

public class SomeKey extends SomeWritable implements
                WritableComparable<SomeKey> {

        private String _someOtherString;

        public String getSomeOtherString() {
                return _someOtherString;
        }

        public void setSomeOtherString(final String someOtherString) {
                _someOtherString = someOtherString;
        }

        @Override
        public void write(final DataOutput out) throws IOException {
                super.write(out);
                out.writeUTF(_someOtherString);
        }

        @Override
        public void readFields(final DataInput in) throws IOException {
                super.readFields(in);
                _someOtherString = in.readUTF();
        }

        @Override
        public int compareTo(final SomeKey o) {
                if (o == null) {
                        return 1;
                }
                if (o == this) {
                        return 0;
                }
                final int c1 = compare(_someOtherString, o._someOtherString);
                if (c1 != 0) {
                        return c1;
                }
                final int c2 = compare(getString1(), o.getString1());
                if (c2 != 0) {
                        return c2;
                }
                return compare(getString2(), o.getString2());
        }
}

1 个答案:

答案 0 :(得分:0)

我解决了这个问题:为了确保相同的密钥始终分配给同一个reducer,密钥的hashCode()必须基于密钥中的当前值来实现。即使它们是可变的。有了这个,一切正常。

必须非常小心,不要在集合中使用这些类型或在地图等中使用键。