Hadoopは、MapReduceプログラミングモデルを使用して、マップの入力と出力のデータ処理を行い、キーと値のペアとして表される関数を削減します。これらは、分散アーキテクチャのさまざまなマシンに配置されたデータセットの並列実行の対象となります。プログラミングパラダイムは、mapとreduceの手法を使用しながら組み合わせるという点で、本質的に機能的です。この記事では、MapReduceモデルを紹介します。特に、単純なテキストから構造化されたバイナリオブジェクトまで、さまざまな形式のデータがどのように使用されるかを紹介します。
MapReduceタイプ
マッピング キーと値のペアで提供されるデータ要素のリストを処理するコア手法です。 map関数は、リストのキーと値のペアとして定義された個々の要素に適用され、新しいリストを生成します。 Hadoopのマップおよびリデュース機能の一般的な考え方は次のように説明できます。
map: (K1, V1) -> list (K2, V2) reduce: (K2, list(V2)) -> list (K3, V3)
キーと値のペアの入力パラメーターは、それぞれK1とV1で表され、出力ペアのタイプであるK2とV2とは異なります。削減機能は、マップによって出力された同じ形式を受け入れますが、削減操作の出力のタイプは、K3とV3で異なります。このためのJavaAPIは次のとおりです。
public interface Mapper<K1, V1, K2, V2> extends JobConfigurable, Closeable { void map(K1 key, V1 value, OutputCollector<K2, V2> output, Reporter reporter) throws IOException; } public interface Reducer<K2, V2, K3, V3> extends JobConfigurable, Closeable { void reduce(K2 key, Iterator<V2> values, OutputCollector<K3, V3> output, Reporter reporter)throws IOException; }
OutputCollector Mapperによるデータ出力の収集を容易にするMap-Reduceフレームワークの一般化されたインターフェースです。 またはレデューサー 。これらの出力は、ジョブの中間出力にすぎません。したがって、それらはタイプでパラメーター化する必要があります。 レポーター Map-Reduceアプリケーションが進行状況を報告し、カウンターとステータス情報を更新するのを容易にします。ただし、combine関数を使用する場合は、reduce関数と同じ形式になり、出力はreduce関数に送られます。これは次のように説明できます:
map: (K1, V1) -> list (K2, V2) combine: (K2, list(V2)) -> list (K2, V2) reduce: (K2, list(V2)) -> list (K3, V3)
K3がK2で、V3がV2である変数名を除いて、combine関数とreduce関数は同じ型を使用することに注意してください。
パーティション関数は、中間のキー値タイプで動作します。中間マップ出力のキーの分割を制御します。キーは、一般的なハッシュ関数を使用してパーティションを導出します。パーティションの総数は、ジョブの削減タスクの数と同じです。パーティションは、値を無視するキーによってのみ決定されます。
public interface Partitioner<K2, V2> extends JobConfigurable { int getPartition(K2 key, V2 value, int numberOfPartition); }
これが、要するにMapReduceタイプの重要な本質です。
入力フォーマット
Hadoopは、テキストファイルからデータベースまで、さまざまな形式を受け入れて処理する必要があります。 input splitと呼ばれる入力のチャンク 、は単一のマップによって処理されます。各分割はさらに、キーと値のペアで処理するためにマップに与えられた論理レコードに分割されます。データベースのコンテキストでは、分割とは、 DBInputFormat によって行われるように、SQLテーブルからタプルの範囲を読み取ることを意味します。 LongWritablesを作成します キーとしてレコード番号を含み、 DBWritables 値として。入力分割用のJavaAPIは次のとおりです。
public interface InputSplit extends Writable { long getLength() throws IOException; String[] getLocations() throws IOException; }
InputSplit マッパーによって処理されるデータを表します 。これはバイト単位の長さを返し、入力データへの参照を持ちます。これは、入力に関するバイト指向のビューを提示し、 RecordReaderの責任です。 これを処理し、レコード指向のビューを提示するジョブの。ほとんどの場合、 InputSplitは扱いません。 InputFormatによって作成されているため直接 。 InputFormatの責任です 入力分割を作成し、それらをレコードに分割します。
public interface InputFormat<K, V> { InputSplit[] getSplits(JobConf job, int numSplits) throws IOException; RecordReader<K, V> getRecordReader(InputSplit split, JobConf job, throws IOException; }
JobClientはgetSplits()を呼び出します 適切な数の分割引数を持つメソッド。実際の分割数は指定された数と異なる場合があるため、指定された数はヒントです。分割が計算されると、それはジョブトラッカーに送信されます。ジョブトラッカーは、保管場所を使用してタスクトラッカーのマップタスクをスケジュールします。次に、tasktrackerは、 getRecordReader()を呼び出して、分割を渡します。 InputFormatのメソッド RecordReaderを取得するには 分割のために。
FileInputFormat ファイルデータソースの基本クラスです。ジョブ入力として含まれるファイルと、分割を生成するための定義を特定する責任があります。
Hadoopには、テキスト形式で提供されることが多い非構造化データの処理も含まれます。 TextInputFormat デフォルトのInputFormat そのようなデータのために。
SequenceInputFormat バイナリ入力を受け取り、バイナリキーと値のペアのシーケンスを格納します。
同様に、DBInputFormatは、JDBCを使用してリレーショナルデータベースからデータを読み取る機能を提供します。
出力フォーマット
出力フォーマットクラスは、対応する入力フォーマットクラスに類似しており、逆方向に機能します。
たとえば、 TextOutputFormat は、レコードをプレーンテキストファイルとして書き込むデフォルトの出力形式ですが、キー値は任意のタイプであり、 toString()を呼び出すことによって文字列に変換します。 方法。キー値文字はタブ文字で区切られますが、これはテキスト出力形式の区切り文字プロパティを操作することでカスタマイズできます。
バイナリ出力の場合、 SequenceFileOutputFormatがあります バイナリ出力のシーケンスをファイルに書き込みます。バイナリ出力は、出力がさらなるMapReduceジョブへの入力になる場合に特に役立ちます。
リレーショナルデータベースおよびHBaseへの出力形式は、 DBOutputFormatによって処理されます。 。縮小された出力をSQLテーブルに送信します。たとえば、HBaseの TableOutputFormat MapReduceプログラムがHBaseテーブルに格納されているデータを処理し、それを使用してHBaseテーブルに出力を書き込むことができるようにします。
結論
つまり、これがMapReduceのタイプとフォーマットの核心です。詳細については、以下のリファレンスのリストを参照してください。 Java APIの機能については、プログラミングに飛び込んだときにのみ明らかになる複雑な詳細がたくさんあります。詳細については、Apache Hadoop Java APIのドキュメントを参照し、いくつかのプラクティスのコーディングを開始してください。
参照
- トムホワイト、 Hadoop The Definitive Guide 、オライリー
- Apache HadoopJavaAPIドキュメント