Редукторы всегда будут работать параллельно, независимо от того, используете ли вы потоковую передачу или нет (если вы этого не видите, убедитесь, что конфигурация задания настроена на несколько задач сокращения - см. Mapred.reduce.tasks в вашем кластере или настройка работы). Разница в том, что фреймворк упаковывает вещи немного приятнее для вас, когда вы используете Java, а не потоковую передачу.
Для Java задача сокращения получает итератор для всех значений для определенного ключа. Это позволяет легко проходить значения, если вы, скажем, суммируете выходные данные карты в своей задаче сокращения. При потоковой передаче вы буквально получаете поток пар ключ-значение. Вы гарантированно гарантируете, что значения будут упорядочены по ключу, и что для данного ключа не будет разбито между задачами сокращения, но любое отслеживание состояния вам нужно. Например, в Java ваша карта выводится на ваш редуктор символически в виде
key1, {val1, val2, val3}
key2, {val7, val8}
При потоковой передаче ваш вывод выглядит как
key1, val1
key1, val2
key1, val3
key2, val7
key2, val8
Например, чтобы написать редуктор, который вычисляет сумму значений для каждого ключа, вам понадобится переменная для хранения последнего ключа, который вы видели, и переменная для хранения суммы. Каждый раз, когда вы читаете новую пару ключ-значение, вы делаете следующее:
- проверить, отличается ли ключ от последнего ключа.
- если это так, выведите ключ и текущую сумму и обнулите сумму до нуля.
- добавить текущее значение к вашей сумме и установить последний ключ для текущего ключа.
НТН.