Mímisbrunnr知恵の泉

← データエンジニアリング 一覧

🎓 レベル:標準 | 重要度:A(必須)

📎 前提:バッチ処理とストリーム処理 | 関連:Sparkの基礎シャッフルとパーティショニング

要点(BLUF)

概念 ── 分割統治を分散に

「全文書から単語の出現数を数える」を、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の設計思想です。

⚠️ よくある落とし穴

対応ラボ

data-engineering-study/labs/06_distributed.pyPYTHONIOENCODING=utf-8 で実行・map/shuffle/reduceのワードカウントを確認済み)。

関連

第6章 分散処理 目次