クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

大きなファイルを複数の機械に分ける(HDFS)

このレッスンのあとで: ファイルがどう分けられ、並行して処理されるかを説明できます。

55分のレッスンコマンド7件Hadoop ラボ:HDFS と MapReduce、ファイルを置き、単語数を読む

1台に入らない6TBの記録

ある全国チェーンのスーパーは、レジを通るたびに1件の記録を残します。2年たつと、記録は6TBになりました。

本社のどのディスクにも入りません。1台のパソコンでは、一度読み通すだけで8時間ほどかかります。

そこでビッグデータの道具は、ファイルを小さく切って、たくさんの機械に置きます。そして、各機械に自分の分だけ処理させます。

このレッスンのゴール

メモ

ファイルがどう分けられ、並行して処理されるかを説明できます。

キーワード

ことばいみれい
ブロック大きなファイルを決まった大きさに切った一片128MB
NameNodeどのブロックがどこにあるかを知っている機械
DataNodeブロックそのものを預かる機械
レプリカ別の機械に置く、ブロックの写し
map各データを、キーと1の組に変える段階
reduce同じキーの組を足し合わせる段階

学生が入力するセルは、このプレビューでは空白です。

HDFSはファイルをブロックに切る

HDFSは、Hadoopのファイルシステムです。ファイルを、決まった大きさのブロックに切ります。初期値は128MBで、最後のブロックには残りが入ります。

各ブロックはDataNodeに置かれ、さらに別の機械へ写されます。機械が壊れても、何も失われません。NameNodeは1台だけで、ブロックの一覧と置き場所を覚えています。

例: 520MBのファイル

ブロック大きさ残す写しの数置き場所
1から4それぞれ128MBそれぞれ3つ別々の3台のDataNode
58MB3つ別々の3台のDataNode
合計520MB15個の写しNameNodeが持つのは一覧だけ

学生が入力するセルは、このプレビューでは空白です。

ブロックの数を数える

コード: python
# ファイルは、決まった大きさのブロックに切られます。
size_mb = 520
block_mb = 128
full = size_mb // block_mb
rest = size_mb % block_mb
blocks = full
if rest > 0:
    blocks = blocks + 1
print("ブロックの数:", blocks)
print("最後のブロックの大きさ:", rest, "MB")
copies = blocks * 3
print("ディスクに残る写しの数:", copies)
# 520 を 900 に変えて、もう一度実行してみましょう。

ラボは小さな実物です

このラボのDataNodeは1台だけです。そのため、ブロックの写しは3つではなく1つです。考え方は同じで、本物のクラスタは機械が増えるだけです。

ラボのターミナルには、hadoopコマンドがありません。NameNodeのWebアドレスに、curlで尋ねます。

入力フォルダを一覧する

コマンド
curl -s 'http://namenode:9870/webhdfs/v1/user/lab/input?op=LISTSTATUS' | grep -o '"pathSuffix":"[^"]*"'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

ブロックの大きさと長さを尋ねる

コマンド
curl -s 'http://namenode:9870/webhdfs/v1/user/lab/input/sentence.txt?op=GETFILESTATUS' | grep -o '"blockSize":[0-9]*\|"length":[0-9]*'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

写しをいくつ持つか尋ねる

コマンド
curl -s 'http://namenode:9870/webhdfs/v1/user/lab/input/sentence.txt?op=GETFILESTATUS' | grep -o '"replication":[0-9]*'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

フォルダが使うディスクを尋ねる

コマンド
curl -s 'http://namenode:9870/webhdfs/v1/user/lab/input?op=GETCONTENTSUMMARY' | grep -o '"spaceConsumed":[0-9]*'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

よくある間違い

注意

NameNodeがファイルを持っていると考えがちです。実際に持つのは、ブロックの一覧と置き場所だけです。データそのものはDataNodeにあります。「中身を持つのは誰か」と考えると、答えはDataNodeです。

MapReduceは仕事をデータへ送る

6TBをネットワークで運ぶと、とても遅くなります。そこでHadoopは、小さなプログラムを、ブロックを持つ機械へ送ります。

各機械は、自分のブロックにだけmapを実行し、ほかの機械とは話しません。できた組はキーごとに集められます。これをシャッフルと呼びます。最後にreduceが、集まりごとに足し合わせます。

例: レシートの単語を数える

段階ブロック1ブロック2
入力pan milk / milk ricepan rice / pan milk
mappan 1, milk 1, milk 1, rice 1pan 1, rice 1, pan 1, milk 1
シャッフル (単語ごとに集める)pan: 1, 1, 1 / milk: 1, 1, 1 / rice: 1, 1両方のブロックの組がここで出会う
reduce (足し算)pan 3, milk 3, rice 2単語ごとに合計が1つ

学生が入力するセルは、このプレビューでは空白です。

やさしいPythonでmapとreduce

コード: python
# レシートの記録を、2つのブロックに分けたものです。
block_one = ["pan milk", "milk rice"]
block_two = ["pan rice", "pan milk"]

def apply_map(lines):
    # mapの段階: 単語ごとに [単語, 1] の組を作ります。
    pairs = []
    for line in lines:
        for word in line.split():
            pairs.append([word, 1])
    return pairs

def apply_reduce(pairs):
    # reduceの段階: 同じ単語の1を足し合わせます。
    totals = {}
    for pair in pairs:
        word = pair[0]
        if word in totals:
            totals[word] = totals[word] + pair[1]
        else:
            totals[word] = pair[1]
    return totals

everything = apply_map(block_one) + apply_map(block_two)
print(apply_reduce(everything))
# block_two に "rice thyme" という行を足して、もう一度実行してみましょう。

ジョブは結果をHDFSに残す

MapReduceの1回の実行を、ジョブと呼びます。ResourceManagerが仕事を割り当て、結果はファイルとしてHDFSに書かれます。

リデューサーごとに、part-r- と番号のついたファイルができます。空の _SUCCESS というファイルがあれば、ジョブは終わっています。

ジョブの出力フォルダを一覧する

コマンド
curl -s 'http://namenode:9870/webhdfs/v1/user/lab/wordcount-out?op=LISTSTATUS' | grep -o '"pathSuffix":"[^"]*"'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

単語 the の合計を読む

コマンド
curl -s -L 'http://namenode:9870/webhdfs/v1/user/lab/wordcount-out/part-r-00000?op=OPEN' | grep '^the'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

ジョブの終わり方を尋ねる

コマンド
curl -s http://resourcemanager:8088/ws/v1/cluster/apps | grep -o '"finalStatus":"[A-Z]*"'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

さらに先へ: 送る前に足す

ブロック2は、シャッフルへ4つの組を送ります。そのうち2つは「pan 1」です。本物のジョブでは、各ブロックの中で先に足すことができます。この段階をコンバイナーと呼びます。

MapReduceのコードの apply_map を、自分のブロックの合計を組で返すように変えて、実行してください。ブロック2から出る組はいくつになりますか。最後の答えは同じですか。

このラボとソースについて: Hadoop ラボ:HDFS と MapReduce、ファイルを置き、単語数を読む

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。