今日、この女の子はmapreduceについてあなたとチャットしています。吐血と片付け、ベンチに座ります。間違えたら訂正してください。
まず、MapReduceとは何かを理解しましょう。主に2つのステージで構成されています。MapandReduce。ユーザーは、map()とreduce()の2つの関数を作成するだけで済みます。簡単な分散プログラムの計算を完了することができます。
プロセスの紹介:
①②③InputFormat
InputFormatインターフェースは、入力ファイルをHadoopブロックに分割する方法を決定します。InputFormatは、ジョブから分割セットを取得できます。次に、この分割にRecordReader(getRecordReader)を指定して、各分割のデータを読み取ります。
public abstract class InputFormat<K, V> {
public InputFormat() {
}
public abstract List<InputSplit> getSplits(JobContext var1) throws IOException, InterruptedException;
public abstract RecordReader<K, V> createRecordReader(InputSplit var1, TaskAttemptContext var2) throws IOException, InterruptedException;
}
(1)その中で、getSplits(JobContext var1)は、ビッグデータを論理的に多くの部分に分割する役割を果たします。次に、2つのパラメーターがInputSplitに記録されます。最初のパラメーターは、このフラグメントの開始IDであり、2番目のパラメーターはこのフラグメントのデータサイズです。したがって、InputSplitはデータ全体を格納するのではなく、データをフラグメント化する方法を提供します。
(2)createRecordReader(InputSplit var1、TaskAttemptContext var2)メソッドは、InputSplitで定義されたメソッドに基づいています。断片化されたレコードを読み取ることができるRecordReaderを返します。getSplitsは、入力ファイルから計算されたInputSplitを取得するために使用されます。createRecordReader()は、前述のRecordReaderの実装を提供します。Keyをオフセットとして使用し、Valueをデータの各行として使用するLineRecordReaderなどのInputSplitからキーと値のペアを正しく読み取り、createRecordReader()によってLineRecordReaderに返されるすべてのInputFormatsがオフセット値をキーとして使用するようにします。データは、値の形式でスライスから読み取られます。
断片化:
- minSize:InputSplitの最小構成。mapred.min.split.sizeはデフォルトで1Mです。
- ゴールサイズ:totalSize /タスク番号。デフォルトのタスク数は1です。
- blockSize:HDFSのブロックサイズ。デフォルトのブロックサイズは128Mです。
- ブロックサイズは次のとおりです。Math.max(minSize、Math.min(goalSize、blockSize))
- ファイルサイズが128M未満の場合、ファイルはどんなに小さくてもスライスされません。別のスライスになり、処理のためにmaptaskに渡されます。小さなファイルが多数ある場合は、多数のマップタスクが生成されるため、クラスターのパフォーマンスが大幅に低下します。
- コピーの数、いくつかのタスク、およびいくつかのスライスがあります。
④リングバッファに入る
- map関数の論理処理後のデータ出力後、OutPutCollectorコレクタを介してデータが収集され、リングバッファに格納されます。
- リングバッファ領域のサイズはデフォルトで100Mです。保存データが80%に達すると、バッファ領域のデータはディスクにオーバーフローして保存されます。
⑤②オーバーフロー(パーティション、ソート)
- リングバッファ内のデータが容量の80%に達すると、ストレージ用のディスクにオーバーフローします。このプロセス中に、プログラムはデータを分割し(デフォルトはHashPartition)、ソートします(デフォルトはキーに応じた高速ソート)。
- バッファ領域で継続的にオーバーフローするデータは、複数の小さなファイルを形成します。ステップ⑥矢印はたくさんの小さなファイルを指しています
- パーティション:
- データがリングバッファからファイルにオーバーフローすると、ユーザー定義のパーティション関数に従ってパーティション分割されます。ユーザーが関数をカスタマイズしない場合、プログラムはデフォルトのパーティショナーを使用してハッシュ関数を介してパーティションを作成します。利点ハッシュパーティションの利点は、より柔軟であるということです。、データタイプとは関係なく、簡単な実装で、reducetaskの数を設定するだけで済みます。パーティション分割の目的は、大きなデータブロック全体を複数のデータブロックに分割することです。これらのデータブロックは、複数のreducetasksによって処理され、複数のファイルを出力します。通常、カスタムパーティションは、出力データを区別する必要がある場合に使用されます。たとえば、上記のトラフィック統計の場合、最終的な出力データを携帯電話番号の州に応じて保存するために複数のファイルに分割する必要がある場合、カスタムパーティションが必要です。機能し、ドライバーのパーティションの数と同じ数のreduceタスクを設定し(job.setNumReduceTasks(5);)、自分で定義したパーティションを指定します(job.setPartitionerClass(ProvincePartitioner.class))。統一された出力結果を取得する必要がある場合、パーティションをカスタマイズしたり、reducetasksの数を設定したりする必要はありません(デフォルトは1)。
- カスタムパーティション関数は、データスキューの問題を引き起こすことがあります。つまり、一部のパーティションには大量のデータがあり、各パーティションのデータ量が不均一であるため、ジョブ時間全体が最も長い処理時間での削減に依存します。これは可能な限り避けるべきですそれは起こりました。
-ソート: - mapreduceプロセス全体には、データの複数の並べ替えが含まれます。リングバッファでオーバーフローしたファイル、オーバーフローした小さなファイルは大きなファイルにマージされ、reduce側の複数のパーティションデータは1つの大きなパーティションデータにマージされます。すべてを並べ替える必要があります。 this並べ替えルールは、キーのcompareToメソッドに基づいています。
- マップ側で出力されるデータの順序は、データが2つの間でソートされるため、必ずしもリデュース側での入力データの順序ではありませんが、リデュース側でファイルに表示される順序は、機能を減らします。reduce関数がない場合は、ドライバー関数でreduceの数を明示的に0に設定します(0に設定すると、reduceフェーズがなく、シャッフルフェーズがないため、データが並べ替えられてグループ化されません)、それ以外の場合、reduceロジックはありませんが、シャッフルフェーズがあります。マップ側がデータを処理した後にデータがファイルに保存される順序は、マップ関数が書き込まれる順序ではなく、順序です。グループ化と並べ替えをシャッフルした後。
ʻマージ(コンバイナー追加)
-ここにコンバイナーを追加しました、
- オーバーフローした複数の小さなファイルの領域がマージされ(領域0と領域0が1つの領域0にマージされます)、大きなファイルが形成されます。
- マージして並べ替えることにより、エリア内のデータが正しいことを確認します
- これらの複数のパーティションファイルは、マージと並べ替えによって大きなファイルにマージされ、キー値に従ってグループ化されます(キー値が同じ場合、値値はイテレータの形式でグループ化されます)。
-combiner(map端的reduce)
- クラスターの帯域幅によってmapreduceジョブの数が制限されるため、mapタスクとreduceタスク間のデータ転送は可能な限り回避する必要があります。Hadoopを使用すると、ユーザーはマップの出力データを処理できます。ユーザーはコンバイナー関数をカスタマイズできます(マップ関数やreduce関数と同様)。そのロジックは通常、reduce関数と同じです。コンバイナーの入力は次の出力です。マップ、およびコンバイナの出力は、reduceの入力として使用されます。多くの場合、reduce関数をコンバイナー関数(job.setCombinerClass(FlowCountReducer.class);)として直接使用できます。
- コンバイナは最適化されたソリューションであるため、コンバイナ関数が呼び出される回数を決定することはできません。リングバッファがファイルをオーバーフローしたときにコンバイナ関数を呼び出すか、オーバーフローした小さなファイルがマージされたときにコンバイナを呼び出すことができます。大きなファイル。ただし、コンバイナー関数が何度呼び出されても、最終結果に影響を与えないようにするためです。
- したがって、すべての処理ロジックがコンバイナーコンポーネントを使用できるわけではありません。一部のロジックは、コンバイナー関数を使用した後、最終的な還元の出力結果を変更します(複数の数値の平均を見つける、コンバイナーを使用して出力結果の平均を見つけることはできません)各マップの値。次に、これらの平均の平均を見つけます。これにより、結果が正しくなくなります)。
- コンバイナの意味は、各マップタスクの出力をローカルに要約して、ネットワーク送信の量を減らすことです。(最初にreduceに渡されるデータは(a、(1,1,1,1,1,1 ...))です。コンバイナーを使用すると、reduceに渡されるデータは(a、(4,2,3、 5 ...)))
- コンバイナーがない場合、ステップはありません。
⑧グループ
- reduceの入力データは、キーが等しいかどうかによってグループに分けられます。キーが等しい場合、これらのキーに対応する値は、イテレータオブジェクトとしてreduce関数に渡されます。reduceによって取得される入力データは次のとおりです。最初のグループ:(a、(1,1,1,1,1、...))2番目のグループ:(b、(1,1,1,1,1。。 。))。reduce関数は、データセットごとに1回呼び出されます。
⑨マージ
- reducetaskを実行しているノードは、プロセス8を介して、独自のパーティションデータを複数のマップタスクからローカルディスクの作業ディレクトリにダウンロードします。これらの複数のパーティションファイルは、マージと並べ替えによって大きなファイルにマージされ、キー値に従ってグループ化されます(キー値が同じ場合、値値はイテレータの形式でグループ化されます)。
⑩reducetask
- reducetaskは、グループ化およびソートされたデータをローカルの作業ディレクトリから取得し、データに対してreduce関数で論理処理を実行します。
11.出力
- 各reducetaskは結果ファイルを出力します。