Skip to main contentSkip to user menuSkip to navigation

MapReduce

Master MapReduce: distributed data processing paradigm, Hadoop ecosystem, and parallel computing.

35 min readIntermediate
Not Started
Loading...

What is MapReduce?

MapReduce is a distributed batch-processing model that transforms independent input records into intermediate key-value pairs, groups every value for the same logical key, and reduces each group into output. The runtime owns input splitting, task scheduling, shuffle transfer, retries, and output commit.

It matters when a large offline job can be expressed as parallel scans and key-based aggregation over data already stored across a cluster. Core invariant: all intermediate records for one reduce key must reach exactly one logical reducer invocation, while task retries must not publish duplicate or partial final output.

MapReduce commonly runs with HDFS for storage and YARN for resource scheduling. Use Spark, Flink, or an interactive query engine when iterative, streaming, or low-latency execution is the primary requirement.

Follow one record through the execution graph

  1. 1

    Plan

    Split immutable input

    Create logical input splits, assign record readers, and prefer workers near the HDFS blocks without coupling correctness to locality.

  2. 2

    Transform

    Map records independently

    Parse each input record and emit zero or more typed intermediate key-value pairs without relying on mapper execution order.

  3. 3

    Compress

    Combine locally when safe

    Apply associative and commutative partial aggregation to reduce mapper spill and network volume; never require a combiner for correctness.

  4. 4

    Exchange

    Partition, shuffle, and sort

    Choose a reducer for every key, transfer partitions, merge spills, sort keys, and group values so equal keys meet.

  5. 5

    Aggregate

    Reduce each key group

    Apply reducer logic to a key and its values, then write task-attempt output into a temporary commit location.

  6. 6

    Publish

    Commit complete output

    Atomically promote only successful task or job output so retries and speculative attempts do not expose duplicates.

Map, combine, shuffle, and reduce a small word count

Size map waves, shuffle bytes, and reducer partitions

Input bytes alone do not determine duration. Split size controls task count, cluster slots control waves, mapper selectivity controls shuffle, and reducer count controls partition size and output files.

MapReduce execution lab

Size task waves and shuffle pressure

Change the input layout, cluster slots, reducer count, intermediate-data ratio, combiner effect, and rack bandwidth. Inspect each phase instead of collapsing the job into one opaque duration.

Execution verdict

The illustrative job keeps phase work balanced

Map waves, shuffle transfer, and reducer partitions remain visible and independently tunable.

Mapper tasks

8,000

34 waves across 240 slots

Shuffle traffic

200 GiB

500 GiB before local combine

Per reducer

2.50 GiB

80 output partitions

Modeled duration

113.0 min

Sequential phase envelope

Phase envelope

Map

108.8 min

8,000 tasks in 34 waves

Shuffle and sort

0.8 min

200 GiB over bounded rack bandwidth

Reduce

3.4 min

2.50 GiB average per reducer

This planning model excludes input skew, task startup distribution, spills, disk contention, failures, queueing, speculative duplicates, and output commit. Validate with framework counters and representative jobs.

Read the envelope by phase

  • Map: input splits divided by concurrent slots determine waves; startup and tail variation make tiny tasks expensive.
  • Spill and combine: sort buffers, spill count, compression, and mathematically safe local aggregation determine disk and network work.
  • Shuffle: intermediate bytes cross machines and racks while reducers fetch, merge, and sort mapper partitions.
  • Reduce: partition bytes, key cardinality, skew, aggregation complexity, and output commit determine the tail.
  • Recovery: failed attempts, speculative duplicates, node loss, queueing, and output cleanup consume reserve beyond the healthy path.

Use combiners only when partial aggregation is valid

A combiner is an optional local optimization. The framework may run it zero, one, or several times, so reducer correctness cannot depend on its execution.

Safe: counts and sums

Integer addition is associative and commutative. Partial counts can be added again without changing the result.

Safe with state: averages

Emit (sum, count) as the partial state, combine both fields, then divide only after the final reduction.

Unsafe: raw average

Averaging partition averages weights groups incorrectly when they contain different record counts.

Unsafe: order-sensitive logic

String concatenation, first/last selection, and non-associative floating-point policies can change with grouping and order.

Test the mapper, combiner, and reducer with different partition boundaries, value orders, duplicate attempts, and empty groups.

Prevent one hot key from owning the reducer tail

Average partition size can look healthy while one logical key sends a large fraction of the shuffle to a single reducer. Adding reducers does not split one key under ordinary hash partitioning.

Loading skew lab

Preparing partition scenarios...

Choose a repair that preserves semantics

  1. Inspect bytes, records, spill, fetch duration, and finish time for every partition, not only the average.
  2. Find whether the skew comes from a hot key, poor range boundaries, a fallback value, or uneven record expansion.
  3. For associative aggregation, salt hot keys across first-stage reducers and merge partial results in a second stage.
  4. For ordered output, sample representative keys and construct range boundaries with headroom for distribution drift.
  5. Verify that retries and the final merge still produce one correct result per logical key.
Spread a hot logical key across bounded salted partitions

Treat shuffle as a distributed storage and network protocol

Mapper output is partitioned, buffered, spilled to local disk, optionally combined and compressed, then fetched and merged by reducers. Every reducer may contact every mapper.

Intermediate data crosses the shuffle boundary

The exchange becomes expensive when mapper output expands, spills repeatedly, crosses racks, or concentrates into a few reducer partitions.

Partition

Mapper buffers

Serialize key-value records, assign reducer partitions, sort in memory, and spill bounded segments to local storage.

Local disk

Spill merge

Merge sorted segments, apply optional combiner and compression, and expose partition files for fetch.

Network

Shuffle fetch

Reducers fetch their partition from every completed mapper attempt with retry, throttling, and checksum behavior.

Grouped keys

Reducer merge

Merge sorted streams, group equal keys, invoke reducer logic, and write attempt-scoped output.

Reduce exchange cost deliberately

  • Filter and project early so the mapper emits only fields needed downstream.
  • Use a safe combiner and intermediate compression after measuring CPU versus network cost.
  • Size sort buffers to reduce spill count without causing garbage collection or memory contention.
  • Prefer map-side joins only when the smaller relation can be distributed and versioned safely.
  • Avoid chaining wide shuffles when a different engine or data layout better matches the computation.

Make retries and speculative execution side-effect safe

The runtime may execute a task more than once because of failure, timeout, preemption, or speculation. User code and output protocols must tolerate duplicate attempts.

  • Keep mapper and reducer functions deterministic for the same versioned input whenever possible.
  • Write only to attempt-scoped temporary paths, then let the output committer publish one winner atomically.
  • Do not call external payment, email, or mutation APIs directly from retryable tasks without idempotency and reconciliation.
  • Quarantine poison records explicitly instead of retrying the same deterministic failure until the job exhausts its budget.
  • Enable speculative execution only when duplicate resource use is acceptable and task duration is comparable.

Speculation can worsen overloaded storage or network dependencies and can duplicate external side effects. It is a tail-latency tool, not a universal fault-tolerance switch.

Choose data layout before tuning tasks

Input design

  • Compact many small files into splittable containers or columnar files suited to the downstream engine.
  • Partition directories by stable pruning dimensions without creating tiny partitions.
  • Use splittable compression when many mappers must scan one large file.
  • Preserve schemas, event-time meaning, and input snapshot identity for reproducible jobs.

Output design

  • Choose reducer count with both partition work and downstream file size in mind.
  • Use map-only jobs when no global key grouping is required.
  • Write versioned output to a new location, validate it, then publish through an atomic pointer or rename contract.
  • Retain job, code, configuration, input, schema, and output lineage for replay and incident analysis.

Know when MapReduce is the wrong engine

Good fit

Large offline scans, independent mapping, key-based aggregation, batch ETL, index construction, and jobs that benefit from durable phase boundaries.

Iterative algorithms

Repeatedly materializing each stage is expensive. Spark or a specialized ML/graph engine may retain useful state across iterations.

Continuous streams

MapReduce has high scheduling and materialization latency. Flink, Kafka Streams, or another stream processor better models unbounded event time.

Interactive queries

Users expect seconds, not batch-job startup and shuffle. Trino, Presto, Druid, ClickHouse, or a warehouse may fit better.

Operate from counters and tail behavior

Monitor every job

  • Input records/bytes, split count, mapper and reducer waves, locality, queue time, and slot utilization
  • Map output bytes/records, combiner input/output, spill count/bytes, merge passes, and intermediate compression
  • Shuffle bytes, failed fetches, cross-rack traffic, reducer partition distribution, and straggler ratio
  • Task failures by cause, attempts, speculative duplicates, killed tasks, poison records, and commit failures
  • Output records/bytes/files, schema checks, data-quality assertions, and downstream publication state

Prepare recovery

  • Re-run from immutable input with versioned code and configuration.
  • Preserve failed-task diagnostics and bounded samples of malformed records.
  • Test node loss, slow disks, unavailable racks, fetch retries, controller restart, and output-commit recovery.
  • Clean abandoned temporary output and old shuffle data without deleting evidence needed for diagnosis.

A healthy MapReduce job is not merely parallel. Its input is splittable, its shuffle is bounded and balanced, its functions tolerate retries, and its final output is published exactly once from reproducible evidence.

No quiz questions available
Could not load questions file
Spotted an issue or have a better explanation? This page is open source.Edit on GitHub·Suggest an improvement