✨ MapReduce: как обрабатывать большие объёмы данных
Если вы работаете только с небольшими таблицами, идея MapReduce может показаться немного странной. Зачем делить одну задачу на множество частей, а потом ещё что-то между ними сортировать и собирать?
Но когда данных уже слишком много для обработки на одной машине, становится важным распределить вычисления между несколькими узлами. Именно для этого и появился MapReduce. Модель стала одной из основ Hadoop и изначально использовалась для обработки больших объёмов данных
😇 Как это работает
У MapReduce три основных этапа:
1. Map
Большой объём данных разбивается на части. Каждая часть обрабатывается отдельно, а результат представляется в виде пар:
ключ → значение
Например, хотим посчитать количество заказов по городам
Mapper может превратить данные в:
Москва → 1 Санкт-Петербург → 1 Москва → 1 Казань → 1 Москва → 1
Каждый узел работает со своей частью данных, поэтому обработку можно выполнять параллельно
2. Shuffle
Вот здесь начинается самое интересное
Нам нужно собрать все значения одного ключа вместе:
Москва → [1, 1, 1] Казань → [1] Санкт-Петербург → [1]
Именно на этапе Shuffle промежуточные результаты перераспределяются между узлами так, чтобы данные с одинаковым ключом попали одному reducer’у. Там же выполняется сортировка Это одна из самых тяжёлых частей MapReduce: данные могут записываться на диск, сортироваться и передаваться между узлами по сети
3. Reduce
Теперь reducer получает:
Москва → [1, 1, 1]
и может посчитать:
Москва → 3
То есть Reduce собирает промежуточные результаты и превращает их в итоговый результат Зачем всё это аналитику?
Представим, что у нас несколько миллиардов событий. Нужно посчитать количество действий пользователей по городам
🌟 На одной машине обработать такой объём может быть долго или вообще невозможно. MapReduce позволяет разделить исходные данные между узлами, обработать их параллельно, собрать значения по ключу и получить итоговую агрегацию
При этом далеко не каждой задаче нужен полный цикл Map → Shuffle → Reduce
Например, если нам нужно просто отфильтровать данные или преобразовать каждую запись независимо от остальных, можно использовать Map-only job — без reducer’ов. Это позволяет избежать дорогого Shuffle
Есть и ещё один способ уменьшить объём данных перед Shuffle — Combiner. Он предварительно агрегирует результаты на узле, чтобы по сети передавалось меньше информации. Например, вместо десятков тысяч единиц можно отправить уже частичную сумму
🤩 Что важно запомнить
Если совсем упростить:
Map — разбили большую задачу на части Shuffle — собрали данные с одинаковыми ключами вместе Reduce — получили итоговый результат
И самое важное здесь — не сами названия Map и Reduce, а идея распределённых вычислений