#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