потоковая передача hadoop: как передать список ключевых значений в reducer?

#python #hadoop #mapreduce #hadoop-streaming

#python #hadoop #mapreduce #потоковая передача hadoop

Вопрос:

итак, когда мы используем Java для написания map/reduce программы, карта собирает данные, а reducer получает список значений для каждого ключа, например

 Map(k, v) -> k1, v1  
    then shuffle and sort happens  
    then reducer gets it  

reduce(k1, List<values>)  
  

для работы. но возможно ли сделать то же самое с python использованием streaming ? Я использовал это в качестве ссылки, и кажется, что reducer получает данные в строке, как указано в командной строке

Ответ №1:

Может быть, это может вам помочь. Я нашел это в apache … org

Настройка способа разделения строк на пары ключ / значение Как отмечалось ранее, когда платформа Map / Reduce считывает строку из стандартного вывода mapper, она разбивает строку на пару ключ / значение. По умолчанию префикс строки до первого символа табуляции является ключом, а остальная часть строки (за исключением символа табуляции) является значением.

Однако вы можете настроить это значение по умолчанию. Вы можете указать разделитель полей, отличный от символа табуляции (по умолчанию), и вы можете указать n-й (n> = 1) символ, а не первый символ в строке (по умолчанию) в качестве разделителя между ключом и значением. Например:

 $HADOOP_HOME/bin/hadoop  jar $HADOOP_HOME/hadoop-streaming.jar 
    -input myInputDirs 
    -output myOutputDir 
    -mapper org.apache.hadoop.mapred.lib.IdentityMapper 
    -reducer org.apache.hadoop.mapred.lib.IdentityReducer 
    -D stream.map.output.field.separator=. 
    -D stream.num.map.output.key.fields=4 
  

В приведенном выше примере -D stream.map.output.field.separator=. в качестве разделителя полей для выходных данных карты указывается «.», а префикс до четвертого «.» в строке будет ключ, а остальная часть строки (за исключением четвертого «.») будет значением. Если в строке меньше четырех «.»s, то вся строка будет ключом, а значение будет пустым текстовым объектом (например, созданным с помощью new Text(«»)).

Аналогично, вы можете использовать -D stream.reduce.output.field.separator=SEP и -D stream.num.reduce.output.fields=NUM для указания разделителя n-го поля в строке выходных данных reduce в качестве разделителя между ключом и значением.

Аналогично, вы можете указать stream.map.input.field.separator and stream.reduce.input.field.separator в качестве разделителя входных данных для отображения / уменьшения входных данных. По умолчанию разделителем является символ табуляции.

Ответ №2:

В потоковой передаче Hadoop mapper записывает пары ключ-значение в sys.stdout . Hadoop выполняет перетасовку и сортировку и направляет результаты в mapper sys.stdin . Как вы на самом деле обрабатываете map и reduce, полностью зависит от вас, если вы следуете этой модели (сопоставьте с stdout, уменьшите из stdin). Вот почему его можно протестировать независимо от Hadoop через cat data | map | sort | reduce командную строку.

Входные данные в reducer — это те же пары ключ-значение, которые были сопоставлены, но они отсортированы. Вы можете перебирать результаты и накапливать итоговые значения, как показано в примере, или вы можете пойти дальше и передать входные данные itertools.groupby() , и это даст вам эквивалент k1, List<values> ввода, к которому вы привыкли, и который хорошо работает reduce() со встроенным.

Дело в том, что вам решать реализовать reduce.

Ответ №3:

PipeReducer — это реализация reducer для потоковой передачи Hadoop. Редуктор получает ключ / значения, повторяет его и отправляет в стандартный интерфейс как ключ / значение, а не ключ / значения. Это поведение потоковой передачи Hadoop по умолчанию. Я не вижу возможности изменить это, если только код Hadoop не был изменен.

 public void reduce(Object key, Iterator values, OutputCollector output,
                 Reporter reporter) throws IOException {

    .....
    while (values.hasNext()) {
    .....
        inWriter_.writeKey(key);
        inWriter_.writeValue(val);
    .....      
    }
}
  

Ответ №4:

Согласно ссылкам на потоковую передачу Hadoop здесь:

  • По умолчанию ключ является префиксом строки перед первой вкладкой.

когда платформа Map / Reduce считывает строку из стандартного вывода mapper, она разбивает строку на пару ключ / значение. По умолчанию префикс строки до первого символа табуляции является ключом, а остальная часть строки (за исключением символа табуляции) является значением.

  • Разделители и позиции клавиш можно настроить.

Однако вы можете настроить это значение по умолчанию. Вы можете указать разделитель полей, отличный от символа табуляции (по умолчанию), и вы можете указать n-й (n> = 1) символ, а не первый символ в строке (по умолчанию) в качестве разделителя между ключом и значением. Например:

  • Пример кода:

    $HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar
    -D stream.map.output.field.separator=.
    -D stream.num.map.output.key.fields=4
    -input myInputDirs
    -output myOutputDir
    -mapper org.apache.hadoop.mapred.lib.IdentityMapper
    -reducer org.apache.hadoop.mapred.lib.IdentityReducer