🎓 レベル:標準 | 重要度:A(必須)
📎 前提:バッチ処理とストリーム処理 | 関連:Sparkの基礎・シャッフルとパーティショニング
要点(BLUF)
- MapReduceは、大きな計算を map(各レコードへ独立に関数を適用)→ shuffle(同じキーを1か所に集める)→ reduce(キーごとに集約) の3段に分ける分散処理モデル。
- mapは完全並列(各データが独立)。だから台数を増やせばそのまま速くなる(水平スケール)。失敗したタスクだけ再実行すればよい(耐障害)。
- 多くの分散処理(SparkもSQLの集約も)は、結局この**「独立に処理→キーで集める→集約」**の形に落ちる。MapReduceは分散処理の“文法”。
概念 ── 分割統治を分散に
「全文書から単語の出現数を数える」を、1台で全部やるのでなく、文書を配って各マシンが部分的に数え、最後に合算します。これがMapReduceの発想=分割統治の分散版です。
flowchart LR
IN["入力(分割)"] --> M["map:各レコードを「キー,値」に変換(並列)"]
M --> SH["shuffle:同じキーを同じreducerへ集める"]
SH --> R["reduce:キーごとに集約(合計など)"]
R --> OUT["出力"]
仕組み ── ワードカウントで見る
map は各語を (word, 1) にし、shuffle が同じ語を集め、reduce が合計します。
def map_fn(doc): # 各文書 -> (語, 1) の列(並列に実行できる)
return [(w, 1) for w in doc.split()]
# shuffle: 同じキーをまとめる(ここがネットワーク移動=コスト源)
# reduce: キーごとに合計
def reduce_fn(values):
return sum(values)
実行結果(実機・純Pythonで再現):
map出力(最初の5件): [('data', 1), ('data', 1), ('pipeline', 1), ('spark', 1), ('pipeline', 1)] ... 計10ペア
shuffle後のキー: ['data', 'map', 'pipeline', 'reduce', 'spark']
reduce結果(語の出現数):
data : 4
pipeline : 2
spark : 2
map : 1
reduce : 1
mapは各文書を独立に処理(並列可能)、shuffleで同じ語を集約先に集め、reduceで合計。dataが4回——これを何千台でも同じ形で実行できるのがMapReduceの威力です。
設計の勘所 ── 段の性質
| 段 | 並列性 | コスト | 失敗時 |
|---|---|---|---|
| map | 完全並列(独立) | 計算(CPU) | そのタスクだけ再実行 |
| shuffle | 全ノード間の移動 | ネットワーク(高い) | 再取得 |
| reduce | キー単位で並列 | 計算(キー偏りに弱い) | そのキーだけ再実行 |
最大のコストはshuffle(→ シャッフルとパーティショニング)。mapとreduceは並列で安いが、間の「キーで集める」ためのデータ移動がネットワークを使い、性能を支配します。「shuffleを減らす」が分散最適化の合言葉です。
なぜそうするか ── スケールと耐障害を同時に
なぜわざわざ3段に分けるのか。水平スケールと耐障害を“設計から”得るためです。mapが独立だから、データを割って台数分の並列にできる(縦に強い1台を買うより、横に並べる方が安く青天井)。各タスクが冪等で独立だから、1台が落ちてもそのタスクだけ別マシンで再実行すれば全体は壊れない(→ べき等性と再実行 と同じ思想)。「速さ」と「壊れにくさ」を、特別な作り込みなしにモデルそのものから引き出すのがMapReduceの設計思想です。
⚠️ よくある落とし穴
- reduceにデータが偏る(1キーに集中)→ そのreducerだけ遅く、全体が律速(→ シャッフルとパーティショニング)。
- mapで状態を共有しようとする → 独立性が壊れ並列化できない。各mapは独立に保つ。
- 何でもMapReduce → 小さいデータには分散のオーバーヘッドが重い。1台で済むなら1台が速い。
- shuffleを意識しない → 不要なgroup by/joinでネットワークを浪費。
対応ラボ
data-engineering-study/labs/06_distributed.py(PYTHONIOENCODING=utf-8 で実行・map/shuffle/reduceのワードカウントを確認済み)。
関連
- これを高速化・汎用化した現代エンジンは Sparkの基礎
- 最大コストのshuffleと偏りは シャッフルとパーティショニング
- 並列集計の親戚はDWHのMPP(→ データウェアハウス)