web-dev-qa-db-ja.com

MapReduceのパーティショニングは正確にどのように機能しますか?

MapReduceプログラミングモデル全般については十分理解していると思いますが、元の論文やその他の情報源を読んだ後でも、特に中間結果の分割に関して、多くの詳細が不明確です。

これまでのMapReduceの理解を簡単にまとめます。潜在的に非常に大きな入力データセットがあり、MRフレームワークによってM個の異なる部分に自動的に分割されます。各部分について、フレームワークは1つのマップタスクをスケジュールします。このタスクは、クラスター内の使用可能なプロセッサ/マシンの1つによって実行されます。 M個のマップタスクはそれぞれ、キーと値のペアのセットを出力します。これは、このマップタスクを実行したマシンと同じマシンにローカルに保存されます。各マシンは、ディスクをRパーティションに分割し、中間キーに基づいて計算された中間キー値のペアをパーティション間で分散します。次に、フレームワークは、個別の中間キーごとに1つのreduceタスクを開始します。これは、使用可能なマシンのいずれかによって再び実行されます。

今私の質問は:

  1. 一部のチュートリアルでは、並行して実行されるタスクをマップして削減することができるようです。これは正解?それぞれの中間キーに対して、1つの削減タスクのみが開始されると想定すると、どうでしょうか。最初の削減タスクを開始する前に、最後のマップタスクが完了するまで待つ必要はありませんか?
  2. 個別の中間キーごとに1つのreduceタスクがあるので、reduceタスクごとに、実行中のマシンが他のすべてのマシンから対応するパーティションをロードする必要がありますか?潜在的に、すべてのマシンは、望ましい中間キーとのキーと値のペアを持つことができるため、reduceタスクごとに、他のすべてのマシンにクエリを実行する必要がある可能性があります。それは本当に効率的ですか?
  3. 元の論文では、パーティション数(R)はユーザーが指定するものでした。しかし、パーティションは削減タスクの入力ではありませんか?もっと正確に言うと、すべてのマシン間で同じ番号のすべてのパーティションの結合が、1つの削減タスクの入力ではありませんか?つまり、Rは通常ユーザーが知らない個別の中間キーの数に依存します。

概念的には、マップの入力と出力、および関数/タスクの削減が明確です。しかし、技術的なレベルでMapReduceをまだ理解していないと思います。誰かが私を理解するのを手伝ってくれませんか?

18
user1494080
  1. マップタスクの実行中に(slowstartと呼ばれる機能を使用して)レデューサータスクを開始できますが、レデューサーはコピーフェーズのみを実行できます(完了したマップタスクから完了した結果を取得します)。最終的なソートと削減を実際に実行する前に完了するマッパー。
  2. レデュースタスクは、実際には、ゼロ、1つ以上のキーを処理します(各キーの個別のタスクではありません)。各レデューサーは、これらの中間出力がソートされ、一度に1つのキーセットを削減する前に、そのパーティションに関連する各マップタスクからマップ出力を取得する必要があります。
  3. 2のメモに戻ります-レデューサータスク(パーティションごとに1つ)は、個別のキーごとに1つのタスクではなく、ゼロ、1つ以上のキーで実行されます。

中間キーがハッシュされて(デフォルトのHashPartitionerを使用している場合)モジュロ化されるため、中間キーの分散とバリエーションを理解し、どのキーパーティションがそのキーを処理するかを決定することも重要です。偶数のレデューサータスク(10)があり、常に偶数にハッシュされる出力キーがあるとします。この場合、これらのハッシュ数と10のモジュロは常に偶数になります。つまり、奇数のレデューサーはデータを処理しないでください。

11
Chris White

クリスの発言の補遺、

基本的に、Hadoopのパーティショナークラス(例:デフォルト HashPartitioner

この関数を実装する必要があります、

int getPartition(K key, V value, int numReduceTasks) 

この関数はパーティション番号を返す役割を果たし、numReduceTasks変数からジョブを開始するときに修正したレデューサーの数を取得します。 HashPartitioner。

上記の関数が返す整数に基づいて、Hadoopは特定のキーのリデュースタスクを実行するノードを選択します。

お役に立てれば。

8