/home/by-natures/dev*

データ界隈で働くエンジニアとしての技術的なメモと、たまに普通の日記。

「Hadoop 徹底入門 第2版」第1部まとめ(HDFS・MapReduce)

Hadoop 徹底入門 第2版」を有志で読み進めているので、そのメモを貼ります。

今回は第1部、4章〜5章、コア技術である HDFS, MapReduce の説明です。

[toc]

Chapter 4 "HDFS

HDFS の特徴

  • 巨大なデータを汎用サーバーのみで扱える
  • 容量にスケーラビリティがある
  • シーケンシャルアクセスで高いスループットを出せる
    • “Write Once, Read Many” 方式
      • データの一部のみ更新することはできない
      • ランダムアクセスは想定していない
    • ブロックサイズを大きくすることで(デフォルトで64MB)、一度にまとめて大量データを扱える
    • 上記性質から、特に大量のログファイルなどの格納に向いている
  • スレーブノードの一部が故障しても、データの損失を回避できる

HDFS の仕組み

  • マスターサーバ(NameNode)、スレーブノード(DataNode)のマスタースレーブ構成
  • DataNode は、ファイルのデータブロックを管理する
  • NameNode は HDFS の全体的な管理を行う。また、NameNode 上で扱うファイルシステムメタデータのメンテナンスを担うのが SecondaryNameNode である
DataNode について(4.2.2節)
  • HDFSJava で実装されたミドルウェアであり、OS よりも上位のレイヤーで提供されるファイルシステム
  • HDFS 上に格納したファイルの実体は、各 DataNode 上のローカルファイルシステムext4など)上のファイルとして存在
  • HDFS 上のデータは「ブロック」と呼ばれるチャンクに分割される
    • デフォルトは 64MB
    • レプリケーション数が3の場合は、3つの DataNode 上に同じ「ブロック」がコピーされる
    • ローカルファイルシステムと違い、1MB しか利用していないときは 1MB 分のディスク領域しか利用しない
      • ただし、あまり細切れにするとブロック数が増えて処理のオーバーヘッドが増加する
    • 全てのレプリカが消失しないよう、同一サーバー・同一ラック上に存在しないように設定することが可能(ラックアウェアネス)
NameNode について(4.2.3節)
メタデータの管理
  • NameNode はデータではなく、メタデータを管理する。「どのブロックがどのファイルのどの部分であるか」
  • メタデータはメモリ上で管理される
  • メタデータには以下の情報が含まれる:ファイル名、親ディレクトリ、サイズ、所有者・所有グループ、属性、ブロックIDとDataNodeのペア(4.4節)
  • ブロックID と DataNode のペアは、DataNode からの申告をもとに動的に構築される
    • DataNode はハートビートパケットの送信タイミングで、自身が保持しているブロックを NameNode に伝える
  • その他の情報は、メモリからディスクへ同期が行われる(逆に言うと、ブロック情報は永続的には保持されない)
  • 下記情報を用いて、クラスタ起動時に初期化が行われる(Write-Ahead Log と同じ仕組み)
  • fsimage をより最新の状態に保つ SecondaryNameNode を利用することも可能
    • NameNode から定期的に fsimage と edits を受け取り、最新の fsimage を作成して NameNode へ戻す
    • NameNode 以外に fsimage を保持することで、メタデータの完全消失も防ぐ
HDFS の使用状況の確認
  • HDFS 全体の使用状況
  • 各 DataNode における HDFS 用領域の使用状況
    • 逼迫している場合には、レプリカを別 DataNode に移す
  • 各ブロックのレプリカ数の管理
    • 足りていなかったり余分であれば、調整(作成 or 破棄)を行う

http://192.168.33.10:50070/dfshealth.jsp

上記 URL で、NameNode から HDFS の使用状況が確認できる

クライアントからのHDFSの操作の受付
  • クライアントは NameNode に読みたいファイルを問い合わせる
  • NameNode は、どのブロックがどの DataNode に存在するかを応答
  • クライアントは、DataNode に直接アクセスしてデータ(ブロック)を読みにいく
DataNode の死活監視
  • DataNode からハートビートのパケットが一定時間受信されないと、その DataNode を故障と見なす
    • ハートビートパケットは、デフォルトでは3秒ごとに送信される
HDFS のファイル読み書きの流れ
  • 書き込み:図4.4(P.69)
    • フロー
      • クライアント -> NameNode: ファイルオープン要求
      • NameNode -> クライアント: ストリーム返却(?)
      • クライアント : ブロックサイズに分けたファイル(パケット)を、データ送信キューに追加
      • クライアント : NameNode に、DataNode のブロック割当を要求
      • NameNode -> クライアント: DataNode パイプラインを返却
      • クライアント : ack 待ちキューに全パケットを保存
      • クライアント -> DataNode: DataNode パイプラインの先頭 DataNode にデータを書き込む
      • 先頭DataNode -> 後続DataNode: パケット伝搬。全 DataNode に書き込めたら、ack 待ちキューから該当パケットを削除
    • 書き込み障害時
      • ack キューに残っているパケットを、データ送信キューに戻し、障害が発生した DataNode を切り離してパイプラインを形成する
  • 読み込み:図4.5(P.71)
    • 書き込み手順と同様、NameNode に問い合わせ、帰ってきた DataNode にクライアントが問い合わせに行く
    • 読み込みの手間を省くため、クライアントはそれぞれの DataNode が持つ対象データのブロックを、DataNode ごとに一度に読み込む

Chapter 5 "MapReduce フレームワーク"

個々のフェーズの動き

Map 処理(図5.2)
  • 入力単位は「スプリット」
    • 通常は、HDFS のファイルのブロックが割り当たる
    • 1レコードずつ読み込み、Map 処理を行う
    • (?) キーバリュー解釈
  • Map 処理後の中間ファイルは、ローカルディスクを利用する
Shuffle & Sort 処理(図5.3)
  • 中間ファイルはキーごとにソートされており、Partitioner が対象の Reducer を決める
    • Partitioner はデフォルトではキーのハッシュ値の剰余で定まる
    • Mapper と Reducer が同じ場合はノード間のデータ通信が発生しない
    • ノード数が多いと、必然的にノード間のデータ通信量が増え、処理全体の性能問題になりやすい
  • Reducer に集まった中間ファイル群はマージソートされ、それぞれの Key ごとに集められる(パーティション
Reduce 処理(図5.4)
  • 入力単位は「パーティション
    • 中間ファイル(ローカルディスク上)が割り当たる
  • 出力先は HDFS
  • Map 処理と違い、分散しにくい

アーキテクチャ

JobTracker の役割

MapReduce フレームワークが提供する分散処理を制御するためのマスターとして動作する Java プロセス。

単一障害点のなり得るが、HA クラスタ構成を取ることも可能(15章「可用性の向上」)。

  • ジョブの管理
    • Map タスクの割り当て制御
    • Map 処理結果把握
    • ジョブ進捗通知
  • リソース管理
    • 処理の割り当て
    • 処理の投機的実行
    • 処理再割り当て
    • ブラックリスト
    • TaskTracker 死活監視
    • TaskTracker 追加/切り離し
  • ジョブ実行履歴の管理
TaskTracker の役割

Map 処理、Reduce 処理を実行するスレーブノード。

実行においては、「Child プロセス」と呼ばれる Java プロセスを生成する。Child プロセスが処理を終えると、TaskTracker は JobTracker に処理の完了通知を行う。

  • Child プロセスの生成と処理実行
  • Child プロセスの状況確認
  • 処理停止の通知
  • ハートビート通信
  • Map 処理数と Reduce 処理数の把握
JobClient の役割

ユーザーが定義した MapReduce 処理を JobTracker に依頼するためのクライアント。

  • 入力データの分割方針の決定
  • ジョブの依頼
  • アプリケーションの配布
    • データではなく、アプリケーション自体を配布し、通信量を削減する(データローカリティ)
  • 進捗状況の受信
  • ジョブの管理

動作確認

JobTracker 管理画面

http://localhost:50030/jobtracker.jsp

  • 上記画面で、JobTracker のステータスが確認できる
  • 404 Not Found となる場合は、JobTracker を再インストールするのがよい…と Web 上では散見される(未試行)
Tips
サンプルの実行ユーザーについて

5.5.3 節の動作確認は適切なユーザーでコマンドを実行する必要がある。特に root ユーザーは HDFS 上での特権ユーザーとならないため、注意が必要である(HDFS 上の特権ユーザーは、NameNode 実行ユーザー)

[誤]
[root@vagrant]#       hadoop jar hadoop-examples.jar ...
[正1]
[sampleuser@vagrant]$ hadoop jar hadoop-examples.jar ...
[正2]
[hoge@vagrant]$       sudo -u sampleuser hadoop jar hadoop-examples.jar ...

また、実行権限などが付与されていない場合は、hdfs dfs -chown コマンドなどで随時調整する。