为什么hbase KeyValueSortReducer需要对所有KeyValue进行排序

时间:2016-05-05 09:34:29

标签: hadoop hbase phoenix bulk-load

我最近正在学习Phoenix CSV批量加载,我发现org.apache.phoenix.mapreduce.CsvToKeyValueReducer的源代码会在一行中的列很大时导致OOM(java堆内存不足)(在我的情况下,一列中有44列)行和一行的平均大小是4KB)。

此外,此类与hbase批量减载类 - KeyValueSortReducer类似。这意味着在我的案例中使用KeyValueSortReducer时可能会发生OOM。

所以,我有一个问题KeyValueSortReducer - 为什么需要首先对treeset中的所有kv进行排序然后将它们全部写入上下文?如果我删除了树集排序代码并将所有kvs直接转换为上下文,结果会有所不同或是错误的吗?

我期待着你的回复。祝你好运!

这是KeyValueSortReducer的源代码:

public class KeyValueSortReducer extends Reducer<ImmutableBytesWritable, KeyValue, ImmutableBytesWritable, KeyValue> {
  protected void reduce(ImmutableBytesWritable row, java.lang.Iterable<KeyValue> kvs,
      org.apache.hadoop.mapreduce.Reducer<ImmutableBytesWritable, KeyValue, ImmutableBytesWritable, KeyValue>.Context context)
  throws java.io.IOException, InterruptedException {
    TreeSet<KeyValue> map = new TreeSet<KeyValue>(KeyValue.COMPARATOR);
    for (KeyValue kv: kvs) {
      try {
        map.add(kv.clone());
      } catch (CloneNotSupportedException e) {
        throw new java.io.IOException(e);
      }
    }
    context.setStatus("Read " + map.getClass());
    int index = 0;
    for (KeyValue kv: map) {
      context.write(row, kv);
      if (++index % 100 == 0) context.setStatus("Wrote " + index);
    }
  }
}

2 个答案:

答案 0 :(得分:2)

请查看this case study。有一些要求,您需要将键值对订购到HFile的同一行。

答案 1 :(得分:1)

1.主要问题:为什么hbase KeyValueSortReducer需要对所有KeyValue进行排序?

感谢RamPrasad G的回复,我们可以查看案例研究:http://www.deerwalk.com/blog/bulk-importing-data/

本案例研究将告诉我们更多关于hbase批量导入和reducer类 - KeyValueSortReducer的信息。 在KeyValueSortReducer reduce方法中排序所有KeyValue的原因是HFile需要这种排序。你可以专注于这一部分:

  

减少时经常出现的问题是词汇排序。当从reducer输出的keyvalue列表没有排序时,会发生这种情况。一个示例是单个行的限定符名称不以词汇递增顺序写入。另一种情况是,在同一个reduce方法中写入多行时,行id不以词汇递增的顺序写入。这是因为reducer输出永远不会被排序。所有排序都发生在mapper输出的keyvalue上,然后才进入reduce方法。因此,它尝试以递增方式添加从reduce方法输出的keyvalue,假设它是预先排序的。因此,在将keyvalue写入上下文之前,必须将它们添加到排序列表中,如TreeSet或HashSet,并使用KeyValue.COMPARATOR作为比较器,然后按排序列表指定的顺序写入它们。

因此,当您的列非常大时,它将使用大量内存进行排序。 作为KeyValueSortReducer的源代码记忆:

/**
 * Emits sorted KeyValues.
 * Reads in all KeyValues from passed Iterator, sorts them, then emits
 * KeyValues in sorted order.  If lots of columns per row, it will use lots of
 * memory sorting.
 * @see HFileOutputFormat
 */

2.引用的问题:为什么Phoenix CSV BulkLoad reducer casue OOM?

Phoenix CSV BulkLoad reducer casue OOM的原因是PHOENIX-2649。 由于比较器内部CsvTableRowKeyPair错误比较两个CsvTableRowKeyPair并使所有行在一个reduce调用中通过一个reducer, 在我的情况下,它会迅速导致OOM。

幸运的是,凤凰队已经修复了4.7版本的这个问题。如果您的凤凰版本低于4.7,请注意并尝试更新您的版本, 或者你可以修补你的版本。

我希望这个答案可以帮到你!