Hadoop輪読会第6章

6,727 views

Published on

0 Comments
7 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,727
On SlideShare
0
From Embeds
0
Number of Embeds
129
Actions
Shares
0
Downloads
66
Comments
0
Likes
7
Embeds 0
No embeds

No notes for slide
  • (プロセス)
  • リソース ・ジョブの JAR ( mapred.submit.replication プロパティで複製数をコントロール) ・設定ファイル ・計算された入力スプリット
  • コア数とメモリ数
  • クラッシュやスローダウン。 デフォルトは 10 分
  • yahoo の capacity scheduler と facebook の Fair Scheduler
  • contrib から持ってきて CLASSPATH 通して使用
  • map や reduce の処理に影響を与えないくらい
  • Hadoop輪読会第6章

    1. 1. <ul><li>Hadoop 本輪読会 </li></ul><ul><li>6 章 MapReduce の動作 </li></ul> 桑野 章弘
    2. 2. 自己紹介 <ul><li>桑野 章弘 (id:akuwano, twitter:kuwa_tw) </li></ul><ul><li>渋谷で働く IT 会社 </li></ul><ul><li>インフラエンジニア </li></ul>
    3. 3. 6 章  MapReduce の動作
    4. 4. はじめに <ul><li>Hadoop の MapReduce がどのように動作するのか ? </li></ul>
    5. 5. 6.1 MapReduce ジョブの実行の内幕 <ul><li>MapReduce の実行 </li></ul><ul><ul><li>やることは、 JobClient.runJob(conf) だけ! </li></ul></ul><ul><ul><li>だけどその裏では様々なプロセスが動いている </li></ul></ul>P169
    6. 6. 6.1 MapReduce ジョブの実行の内幕 <ul><li>裏で動いている登場人物 </li></ul><ul><ul><li>jobClient </li></ul></ul><ul><ul><li>jobtracker </li></ul></ul><ul><ul><ul><li>ジョブの実行管理。 JobTracker をメインクラスに持つ Java アプリケーション </li></ul></ul></ul><ul><ul><li>tasktracker </li></ul></ul><ul><ul><ul><li>ジョブを分割して出来たタスク実行。 TaskTracker をメインクラスに持つ Java アプリケーション </li></ul></ul></ul><ul><ul><li>分散 FS ( HDFS など) </li></ul></ul><ul><ul><ul><li>各プロセス間でのジョブのファイルを共有する為に使用する </li></ul></ul></ul><ul><li>どのように実行されるか、ステップ毎に説明していきます。 </li></ul>
    7. 7. MapReduce ジョブの実行遷移図 MapReduce プログラム JobClient JobTracker TaskTracker 子 Map タスク あるいは Redule タスク 共有ファイル システム ( HDFS 等) 1. ジョブの実行 2. 新規ジョブの取得 4. ジョブの投入 3. ジョブの リソースのコピー 5. ジョブの初期化 6. 入力スピリットの取得 8. ジョブのリソースの取得 9. 起動 10. 実行 7. ハートビート (タスクの返却) クライアント JVM クライアントノード Jobtracker ノード tasktracker ノード 子 JVM
    8. 8. 6.1.1 ジョブの投入 [ ステップ1 ] <ul><li>JobClient で runJob() メソッドの実行 </li></ul><ul><ul><li>JobClient のインスタンス生成し、 submitJob() メソッド呼び出し </li></ul></ul><ul><ul><li>その後 runJob は定期的(毎秒)にジョブの進行状況を監視 </li></ul></ul>
    9. 9. 6.1.1 ジョブの投入 [ ステップ 2 ~ 4] <ul><li>submitJob() メソッド </li></ul><ul><ul><li>JobTracker で getNewJobId() メソッドに新しいジョブ ID の要求 </li></ul></ul><ul><ul><li>ジョブの出力条件が正しいのかチェック </li></ul></ul><ul><ul><li>入力スプリットの計算 </li></ul></ul><ul><ul><li>ジョブ実行に必要なリソースを共有ファイルシステムへコピーする </li></ul></ul><ul><ul><li>JobTracker の submitJob() メソッドを呼び出す </li></ul></ul>
    10. 10. 6.1.2 ジョブの初期化 [ ステップ 5 ~ 6] <ul><li>JobTracker の submitJob() メソッド </li></ul><ul><ul><li>submitJob() を呼び出したジョブをキューに保存 </li></ul></ul><ul><ul><li>ジョブスケジューラは定期的にキューからジョブを取り出し初期化しオブジェクトを作成 </li></ul></ul><ul><ul><li>共有ファイルシステムから入力スプリットを取得 </li></ul></ul><ul><ul><li>取得したスプリットごとに map タスクを作成 </li></ul></ul><ul><ul><li>Reduce タスクも作成される。 </li></ul></ul><ul><ul><ul><li>作成数は mapred.reduce.tasks プロパティで決定される </li></ul></ul></ul>
    11. 11. 6.1.3 タスクの割り当て [ ステップ 7] <ul><li>tasktraker 郡からのハートビート </li></ul><ul><ul><li>定期的な死活監視とメッセージの送出 </li></ul></ul><ul><ul><li>タスク実行可否の通知 </li></ul></ul><ul><ul><li>タスクが実行可能であればタスクを割り振る </li></ul></ul><ul><ul><li>複数ジョブの jobtracker でのスケジューリング </li></ul></ul><ul><ul><ul><li>スケジューリングアルゴリズム( 6.3 で後述) </li></ul></ul></ul><ul><ul><ul><li>tasktracker のスロット( tasktracker のリソースによる) </li></ul></ul></ul>
    12. 12. 6.1.4 タスクの実行 <ul><li>tasktracker によるタスクの実行 </li></ul><ul><ul><li>ジョブに必要なリソースをローカルへコピー </li></ul></ul><ul><ul><li>ローカル作業用ディレクトリに JAR を展開 </li></ul></ul><ul><ul><li>JVM 起動し、タスク実行開始 </li></ul></ul><ul><ul><li>子プロセス( JVM )と親タスク (tasktracker) は常にタスクの進行状況のやりとりを行う </li></ul></ul>
    13. 13. ストリーミングとパイプ <ul><li>map タスク、または reduce タスクから </li></ul><ul><ul><li>ユーザが実行可能な実行ファイルを起動して処理させる為の仕組み </li></ul></ul><ul><ul><li>ストリーミングは標準入出力経由でやりとりする </li></ul></ul><ul><ul><li>パイプはソケット通信でやりとりする </li></ul></ul>
    14. 14. ストリーミングとパイプ ストリーミング TaskTracker 子 Map タスク あるいは Redule タスク 9. 起動 実行 tasktracker ノード 子 JVM ストリーミング タスク 起動 出力キー / 値 入力キー / 値 標準入力 標準出力 TaskTracker 子 Map タスク あるいは Redule タスク 9. 起動 実行 tasktracker ノード 子 JVM C++map あるいは Reduce タスク ソケット 起動 出力キー / 値 パイプ
    15. 15. 6.1.5 進行状況とステータスの更新 <ul><li>ジョブ進行状況のクライアントへの通知 </li></ul><ul><ul><li>タスクは tasktracker へと定期的( 3 秒程度)に情報を通知する </li></ul></ul><ul><ul><li>tasktracker は jobtracker へのハートビートにその tasktracker の全タスクの状態を入れて送る </li></ul></ul><ul><ul><li>jobtracker は tasktracker 郡から送られた統計情報を集約 </li></ul></ul><ul><ul><li>jobClient は jobtracker に毎秒問い合わせを行う </li></ul></ul>
    16. 16. 6.1.5 進行状況とステータスの更新 MapReduce プログラム JobClient JobTracker TaskTracker 子 Map タスク あるいは Redule タスク 共有ファイル システム ( HDFS 等) getJob getJobStatus 9. 起動 ハートビート クライアント JVM クライアントノード Jobtracker ノード tasktracker ノード 子 JVM 進行状況あるいはカウンターの更新 statusUpdate
    17. 17. 6.1.6 ジョブの完了 <ul><li>ジョブの最後のタスクが完了した </li></ul><ul><ul><li>ジョブのステータスを successful </li></ul></ul><ul><ul><li>runJob() メソッドから戻る </li></ul></ul>
    18. 18. 6.2 障害 <ul><li>Hadoop の障害検知 </li></ul><ul><ul><li>タスク </li></ul></ul><ul><ul><li>tasktracker </li></ul></ul><ul><ul><li>jobtracker </li></ul></ul>P176
    19. 19. 6.2.1 タスクの障害 <ul><li>タスクのコードがエラーを投げた場合 </li></ul><ul><ul><li>tasktracker に異常終了を通知し、スロットを空ける </li></ul></ul><ul><ul><li>ストリーミングの場合もタスク失敗となる </li></ul></ul><ul><ul><ul><li>この場合の振る舞いは stream.non.zero.exit.is.failure プロパティで管理 </li></ul></ul></ul>
    20. 20. 6.2.1 タスクの障害 <ul><li>タスク実行中の JVM が突然死した場合 </li></ul><ul><ul><li>tasktracker が JVM プロセス終了を検知 </li></ul></ul><ul><ul><ul><li>タスク失敗 </li></ul></ul></ul>
    21. 21. 6.2.1 タスクの障害 <ul><li>タスク実行中の JVM がハングした場合 </li></ul><ul><ul><li>tasktracker が一定期間実行状況の通知を受けない場合 </li></ul></ul><ul><ul><ul><li>タスク失敗+ JVM プロセスを kill </li></ul></ul></ul><ul><ul><ul><li>ただしストリーミングで実行中のプロセスは残る </li></ul></ul></ul>
    22. 22. 6.2.1 タスクの障害 <ul><li>失敗したタスクの再スケジュール </li></ul><ul><ul><li>前回失敗した tasktracker にはタスクを割り振らない </li></ul></ul><ul><ul><li>失敗回数が一定を越えたタスクは再スケジュール不可 </li></ul></ul><ul><ul><ul><li>失敗してもタスク再スケジュール可にもできる </li></ul></ul></ul><ul><ul><ul><li>タスク試行は失敗回数には入らない </li></ul></ul></ul>
    23. 23. 6.2.2 tasktracker の障害 <ul><li>tasktracker のハートビートが途絶えた場合 </li></ul><ul><ul><li>jobtraker は該当 tasktracker をブラックリストへ登録する </li></ul></ul><ul><ul><li>結果タスクを他 tasktracker へと振り分け </li></ul></ul><ul><ul><li>タスク失敗率が高い場合にもブラックリストに入る </li></ul></ul>
    24. 24. 6.2.3 jobtracker の障害 <ul><li>現在 jobtracker は SPOF </li></ul><ul><ul><li>将来的には ZooKeeper で冗長化するかもしれない </li></ul></ul>
    25. 25. 6.3 ジョブのスケジューリング <ul><li>デフォルトでは FIFO スケジューラ </li></ul><ul><ul><li>優先度付けは可能だがプリエンプション無 </li></ul></ul><ul><ul><li>プラガブルになっているので、複数のスケジューラが存在する </li></ul></ul><ul><ul><ul><li>キャパシティスケジューラ </li></ul></ul></ul><ul><ul><ul><li>フェアスケジューラ </li></ul></ul></ul><ul><ul><ul><li>など </li></ul></ul></ul>P178
    26. 26. 6.3 ジョブのスケジューリング <ul><li>フェアスケジューラ </li></ul><ul><ul><li>各ジョブに対して公平にリソースが割り振る </li></ul></ul><ul><ul><li>ジョブ優先度 </li></ul></ul><ul><ul><li>プリエンプション有 </li></ul></ul><ul><ul><li>default では有効ではない </li></ul></ul>P178
    27. 27. 6.4 シャッフルとソート <ul><li>MapReduce の肝の処理 </li></ul><ul><ul><li>mapreduce では reduce 側への入力はキーでソートされている前提 </li></ul></ul><ul><ul><ul><li>シャッフルとは、レコードのソートを行い map の出力を reduce へと入力する処理 </li></ul></ul></ul>P179
    28. 28. 6.4 シャッフルとソート map タスク reduce タスク map reduce 入力 スプリット メモリ内 バッファ コピーフェーズ ディスク上での マージ パーティション 取得 他の reduce へ 他の map から メモリとディスク上にデータが混在 マージ 出力 ソートフェーズ reduce フェーズ
    29. 29. 6.4.1 シャッフルとソート [map 側 ] <ul><li>出力は単純にディスクに書き出されない </li></ul><ul><ul><li>循環メモリバッファ </li></ul></ul><ul><ul><ul><li>出力が最初に読み込まれる </li></ul></ul></ul><ul><ul><li>スピルファイル </li></ul></ul><ul><ul><ul><li>バッファがある程度溜まった段階でファイルへと書き出す、複数ファイル </li></ul></ul></ul><ul><ul><li>単一ファイルへのマージ </li></ul></ul><ul><ul><ul><li>スピルファイルの出力を単一ファイルへマージする </li></ul></ul></ul>
    30. 30. 6.4.2 シャッフルとソート [reduce 側 ] <ul><li>map 側の出力を集めて reduce 処理を行う </li></ul><ul><ul><li>コピーフェーズ </li></ul></ul><ul><ul><ul><li>各 map から並列で出力をコピー </li></ul></ul></ul><ul><ul><li>ソートフェーズ </li></ul></ul><ul><ul><ul><li>各 map の出力をソート順を保ちつつマージ </li></ul></ul></ul><ul><ul><li>Reduce フェーズ </li></ul></ul><ul><ul><ul><li>マージした入力を reduce 処理へ渡す </li></ul></ul></ul>
    31. 31. 6.4.3 設定のチューニング <ul><li>チューニング項目 </li></ul><ul><ul><li>可能な限りのメモリをシャッフルに当てる </li></ul></ul><ul><ul><li>reduce の中間ファイルをメモリ内に保持 </li></ul></ul><ul><ul><li>バッファサイズの拡張 </li></ul></ul>
    32. 32. 6.4.3 設定のチューニング [map] map の出力を reducer に提供するために使われる、 tasktracker ごとのワーカースレッド数。これはクラスタ単位の設定であり、ジョブ単位には設定することは出来ない。 40 int tasktracker.http.threads map の出力に使われる圧縮コーデック。 org.apache.hadoop.io.compress.DefaultCodec クラス名 mapred.map.outupt.compression.codec combiner を実行する( combiner が指定されている場合)のに必要な最小限のスピルファイル数。 3 int min.num.spills.for.bombine map 出力のメモリバッファと、レコード境界インデックスの両方に適用される。ディスクにスピルを書き出し始めるかどうかの判定をするための利用率の閾値。 10 int io.sort.spill.percent io.sort.mb の中で、 map の出力のレコード境界を保存するために予約される比率。残りの領域は map の出力レコードのために使われる。 0.05 fload io.soft.record.percent map 出力のソートに使われるメモリバッファの量(単位はメガバイト) 100 int io.sort.mb 説明 デフォルト値 型 プロパティ名
    33. 33. 6.4.3 設定のチューニング [reduce] reduce の過程で、 map の出力を保持するために使われるバッファの、総ヒープサイズに対する比率。 reduce フェーズが開始されるためには、メモリ内にある map の出力サイズがこのサイズよりも大きくなければならない。デフォルトでは、 reduce の処理が出来る限りのメモリを使えるようにするため、すべての map の出力は reduce が開始される前にディスク上にマージされている。しかし reducer がそれほどメモリを使わない場合、この値を増やすことでディスクとのやりとりを最小限に抑えられることがある。 0.0 float mapred.job.reduce.input.buffer.percent map の出力をマージし、スピルとしてディスクに書き出すプロセスが開始される、 map 出力数の閾値。 0 以下の値を指定した場合、閾値がない物と見なされ、スピルの動作は mapred.job.shuffle.merge.percent でのみ管理される。 1000 int mapred.inmem.merge.threshold map の出力バッファ( mapred.job.shuffle.input.buffer.percent で指定)に対する使用率の閾値。この値を超えると出力のディスクへのスピルへの書き出しが開始される。 0.66 float mapred.job.shuffle.merge.percent 総ヒープサイズに対する、シャッフルのコピーフェーズ間の map の出力バッファへの割り当て比率 0.70 float mapred.job.shuffle.input.burffer.percent このファイルをソートする際に同時にマージされる最大のストリーム数。 このプロパティは map でも使われる。 10 int io.sort.factor 1 つの map の出力を reduce が取得する際に、失敗したと判定するまでの時間(秒)。 reducer は、この時間内であれば、何回取得に失敗しても繰り返し転送をしてみることができる(その際には、指数関数的に間隔をあけていく) 300 int mapred.reduce.copy.backoff map の出力を reduce にコピーするために使われるスレッド数。 5 int maprd.reduce.parallel.copies 説明 デフォルト値 型 プロパティ名
    34. 34. 6.5 タスクの実行 <ul><li>MapReduce ユーザがタスク実行時に制御できる事 </li></ul><ul><ul><li>投機的実行 </li></ul></ul><ul><ul><li>タスク JVM の再使用 </li></ul></ul><ul><ul><li>不良レコードのスキップ </li></ul></ul><ul><ul><li>タスクの実行環境 </li></ul></ul>P184
    35. 35. 6.5.1 投機的実行 <ul><li>タスクのバックアップ実行 </li></ul><ul><ul><li>低速なタスクが存在する場合にそのタスクを複製、実行 </li></ul></ul><ul><ul><li>先に終了したタスクの結果を使用し、終わらなかったタスクは kill </li></ul></ul><ul><ul><li>最適化の為の処理であり、ジョブ実行の信頼性は変わらない </li></ul></ul><ul><ul><li>投機的実行の為にリソースを食い過ぎる様だと逆効果 </li></ul></ul>
    36. 36. 6.5.2 タスク JVM の再利用 <ul><li>タスクを毎回初期化しないで再利用する </li></ul><ul><ul><li>短い時間に大量に生成されるタスクの場合に有効 </li></ul></ul><ul><ul><li>長時間実行する事で HotSpotJVM の最適化の恩恵も受けられる </li></ul></ul><ul><ul><li>その代わり同じ JVM をシリアルに使用するため、並列度は下がる </li></ul></ul>
    37. 37. 6.5.3 不良レコードのスキップ <ul><li>大量データには不良データは存在する事がある </li></ul><ul><ul><li>不良レコードは例外処理を行う </li></ul></ul><ul><ul><ul><li>mapper, reducer 内の例外処理 </li></ul></ul></ul><ul><ul><ul><li>スキッピングモード </li></ul></ul></ul>
    38. 38. 6.5.4 タスクの実行環境 <ul><li>現在実行している mapper, reducer の情報を知る </li></ul>
    39. 39. 6.5.4 タスクの実行環境 true このタスクが map タスクかどうか boolean mapred.task.is.map 3 ジョブ内でのタスク ID int mapred.task.partition attempt_200811201130_0004_m_000003_0 タスク試行 ID (タスク ID とは別) String mapred.task.id task_200811201130_0004_m_000003 タスク ID String mapred.tip.id job_200811201130_0004 ジョブ ID (フォーマットの説明は「 5.5.2  ジョブの起動」のコラム「ジョブ、タスク、タスク試行 ID 」を参照) String mapred.job.id 例 説明 型 プロパティ名
    40. 40. ストリーミングの環境変数 <ul><li>ストリーミングのプログラムに環境変数を渡す事が可能 </li></ul><ul><ul><li>ただし、アルファベットでも、数字でもない文字はアンダースコアに置き換わる </li></ul></ul><ul><ul><li>mapred.job.id -> os.environ{“mapred_job_id”} </li></ul></ul>
    41. 41. タスクの副作用ファイル <ul><li>通常のキー / バリュー以外の複雑な出力結果がほしい場合 </li></ul><ul><li>タスク毎に別々に作業用ディレクトリを作成する </li></ul><ul><ul><li>投機的実行等でも影響が無い </li></ul></ul>
    42. 42. まとめ <ul><li>Hadoop の MapReduce がどのように動作するのか </li></ul><ul><ul><li>各プロセス間の連携(メソッド呼び出しや、ハートビート) </li></ul></ul><ul><li>MapReduce の障害時の動作 </li></ul><ul><ul><li>各タスク、 tasktracker の障害は冗長取れている </li></ul></ul><ul><ul><li>jobtracker は SPOF なので注意 </li></ul></ul><ul><li>各種設定とチューニング </li></ul><ul><ul><li>スケジューラは適切な物を選択( FIFO は殆どの場合悪手) </li></ul></ul><ul><ul><li>シャッフルの最適化が重要 </li></ul></ul>
    43. 43. ご清聴ありがとうございました。

    ×