Apache Tezの解説 | Hadoop Advent Calendar 2016 #07

こんにちは、小澤です。 この記事はHadoop Advent Calendar 7日目のものとなります。

前回はHiveを使ってHadoop上のデータにSQLでアクセスする方法を紹介しました。
今回はTezについて書かせていただきたいと思います。

Tezとは

Hadoop上で動くフレームワークの一種です。 YARNの登場によって、MapReduce以外の分散処理フレームワークもHadoop上で動くようになりました。 Tezはそれを利用してMapReduceよりも柔軟かつ効率的に分散処理を行うためのフレームワークとなっております。

ただし、TezはMapReduceとは異なり、直接書くというよりは、HiveやPigの裏で実際に動くジョブを効率化させてるために作られているようです。 Tezでジョブを直接書くという場面はあまりなく、HiveやPigから簡単な設定の変更のみほとんど意識せずに使うことが多いかと思います。

TezとMapReduceの違い

MapReduceでは処理の流れが必ずMap → Reduceという形に固定されていました。 これは一見すると単純なことしかできないように見えますが、MapReduceの出力を次のMapReduceに活用するといった多段構成にすることによって多くの処理が実現可能となっています。

そうなってくるとより複雑なことを次々と実装していくのものです。 HiveやPigでは内部では多段のMapReduceになってることはよくありますし、Hadoop上で機械学習を行うようなライブラリも存在しています。

このように多段のMapReduceを活用した複雑な処理が当たり前になってくるとMap → Reduceという形に固定されていることがボトルネックとなる場面が多々出てくるようになります。

MapReduceでは毎回必ずHDFSからデータを読み込みHDFSにデータを書き込みます。 多段になるような複雑なことをしようとするとジョブの実行時間のうちHDFSの読み書きが占める時間が無視できないく多くなるという状況が発生します。 また、処理フローとしても固定されていなければMap → Reduce → Reduceのように書けるのに、Map → Reduce → HDFS → Map → Reduceとしなければならないなど、冗長な部分が含まれるようになります。

そこでこれを改善するたにTezはMapやReduceといった処理を柔軟に組み合わせて最終結果までの一連の流れをDAG(有向非巡回グラフ)で定義できるフレームワークとして登場しました。

tez

なお、上記の図では最初以外のMapもなくなっています。 Mapの処理は1行1行に対して行うものなので、Map → MapやReduce → Mapのような処理は通常一つ目のMapやReduceの中で一緒に処理してしまえることが多いです。 そのため、多段のMapReduceでは省略できないMapが入力をそのまま出力するだけという無駄な操作を含む場合もありました。

コンテナのReuse

Tezには実はもう一つ突起して記載しておきたい事項があります。それはコンテナのreuseにです。 どういう機能かというと通常Hadoopではジョブを実行する際にノードでJVMが立ち上がり、ジョブの終了とものプロセスも終了します。 デーモンとして待機しているわけでありません。 もともとバッチ処理のためのフレームワークということもありレイテンシよりもスループットを重視していたため、このような仕様になっているのですが、どうしてもそこにオーバーヘッドが存在してしまいます。

tezでは

tez.am.container.reuse.enabled=true

と設定しておくことで、一定時間コンテナを確保したままにして起動のオーバーヘッドを削減することができます。 これは是非覚えておく良い設定でしょう。

Tezを使う

次世代のMapReduceとして登場したTezですが、そのままTezで処理を記述することはほとんどありません。 それでも気になるという方は、公式のexamplesを参照するとよいでしょう。

HiveやPigなど裏側の処理でMapReduceに変換していたものをTezに変換するというかたちで使われています。 元々もTezができた頃にはすでにMapReduceを直接書くという場面はあまりなくなってきており、Hadoopを使うにしてもほとんどの場合はこれらを使うようになっていました。

余談ですが、当時はSparkも有名になってきたということもあり、勉強会などでは「MapReduceを直接書くことはほとんどない」という発言を数多く聞いた記憶があります。 MapReduceはもうそれくらい裏方的な存在となっていたのです。

さて、話を戻しますが、HiveやPigでTezを使うのはすごく簡単です。 Hiveの場合、

set hive.execution.engine=tez;

など、hive.execution.engine変数にtezという値を入れてやります。

Pigの場合も起動時に

$ pig -x tez

とするか

set exectype=tez;

と変数を設定してやるかするだけです。

どちらの場合もすでにMapReduceで動いているプログラムを変更する必要はありません。 ただし、パフォーマンスチューニングのための設定などを行っている場合、一部は書き変える必要があるものもあります。

TezはHiveやPigのパッケージに含まれているわけではないので、クラスタ上で利用可能になっていないか、未対応の古いバージョンのHiveやPigが入っている場合には動かないので注意が必要です。

設定自体は非常に簡単に終わるので試しに使ってみるだけでも、ジョブが簡単なものであってもMapReduceと比較して速くなってるのが実感できるくらいの速度向上が見込めると思います。

おわりに

今回はTezについて解説しました。 TezはHiveやPigなどの裏方として活躍するもののため、あまり話題に上がりにくいものでもありますが、使いこなすと非常に強力なフレームワークとなっています。

明日はHiveの話に戻り、実査に利用するうえで必要であったりより高度なトピックであったりする内容を紹介する予定です。
ぜひ、お楽しみに!