Кажется, Hadoop изменяет мой ключевой объект во время итерации по значениям данного вызова - PullRequest
5 голосов
/ 23 мая 2011

Hadoop Версия: 0.20.2 (в Amazon EMR)

Проблема: у меня есть пользовательский ключ, который я пишу во время фазы карты, которую я добавил ниже.Во время вызова Reduce я делаю простую агрегацию значений для данного ключа.Проблема, с которой я сталкиваюсь, заключается в том, что во время итерации значений в вызове Reduce мой ключ изменился, и я получил значения этого нового ключа.

Мой тип ключа:

 class MyKey implements WritableComparable<MyKey>, Serializable {
    private MyEnum type; //MyEnum is a simple enumeration.
    private TreeMap<String, String> subKeys;

    MyKey() {} //for hadoop
    public MyKey(MyEnum t, Map<String, String> sK) { type = t; subKeys = new TreeMap(sk); }

    public void readFields(DataInput in) throws IOException {
      Text typeT = new Text();
      typeT.readFields(in);
      this.type = MyEnum.valueOf(typeT.toString());

      subKeys.clear();
      int i = WritableUtils.readVInt(in);
      while ( 0 != i-- ) {
        Text keyText = new Text();
        keyText.readFields(in);

        Text valueText = new Text();
        valueText.readFields(in);

        subKeys.put(keyText.toString(), valueText.toString());
    }
  }

  public void write(DataOutput out) throws IOException {
    new Text(type.name()).write(out);

    WritableUtils.writeVInt(out, subKeys.size());
    for (Entry<String, String> each: subKeys.entrySet()) {
        new Text(each.getKey()).write(out);
        new Text(each.getValue()).write(out);
    }
  }

  public int compareTo(MyKey o) {
    if (o == null) {
        return 1;
    }

    int typeComparison = this.type.compareTo(o.type); 
    if (typeComparison == 0) {
        if (this.subKeys.equals(o.subKeys)) {
            return 0;
        }
        int x = this.subKeys.hashCode() - o.subKeys.hashCode();
        return (x != 0 ? x : -1);
    }
    return typeComparison;
  }
}

Есть ли что-нибудьне так с этой реализацией ключа?Ниже приведен код, где я сталкиваюсь со смешением клавиш в вызове Reduce:

reduce(MyKey k, Iterable<MyValue> values, Context context) {
   Iterator<MyValue> iterator = values.iterator();
   int sum = 0;
   while(iterator.hasNext()) {
        MyValue value = iterator.next();
        //when i come here in the 2nd iteration, if i print k, it is different from what it was in iteration 1.
        sum += value.getResult();
   }
   //write sum to context
}

Любая помощь в этом будет принята с благодарностью.

1 Ответ

5 голосов
/ 17 мая 2012

Это ожидаемое поведение (по крайней мере, с новым API).

Когда вызывается метод next для лежащего в основе итератора значений Iterable, следующая пара ключ / значение считывается из отсортированного вывода mapper / combiner и проверяется, что ключ все еще является частью того же самогогруппа как предыдущий ключ.

Поскольку hadoop повторно использует объекты, переданные методу Reduce (просто вызывая метод readFields для того же объекта), базовое содержимое параметра Key 'k' будет меняться с каждой итерацией values Iterable.

...