2012-06-13 3 views
6

MapReduceジョブを作成しています。このジョブは、リデューサー内に膨大な数の値で終わることがあります。私はこれらの値がすべて一度にメモリにロードされることに懸念しています。メモリ内のHadoop Reducerの値は?

Iterable<VALUEIN> valuesの基本実装は、必要に応じてメモリに値をロードしますか? Hadoop:The Definitive Guideはこれを示唆しているようですが、「決定的な」答えはありません。

レデューサー出力は入力値よりもはるかに大量になりますが、出力が必要に応じてディスクに書き込まれると思います。

答えて

12

あなたは正しく本を読んでいます。レジューサーは、すべての値をメモリーに格納しません。代わりに、Iterable値リストをループするとき、各Objectインスタンスは再利用されるので、特定の時刻に1つのインスタンスを保持します。

たとえば、次のコードでは、objs ArrayListはループの後に予想されるサイズを持ちますが、すべての要素は同じb/cであり、テキストvalインスタンスはすべての繰り返しで再利用されます。

public static class ReducerExample extends Reducer<Text, Text, Text, Text> { 
public void reduce(Text key, Iterable<Text> values, Context context) { 
    ArrayList<Text> objs = new ArrayList<Text>(); 
      for (Text val : values){ 
        objs.add(val); 
      } 
    } 
} 

(何らかの理由であなたが各ヴァルにさらなる行動を取るようにしたいなかった場合、あなたは深いコピーを作成し、それを保存する必要があります。)もちろん

も、単一の値がメモリよりも大きくなる可能性があり。この場合、開発者は前のMapperでデータをpareしてその値がそれほど大きくないようにすることを推奨します。

更新:Hadoop The Definitive Guide第2版の199〜200ページを参照してください。

This code snippet makes it clear that the same key and value objects are used on each 
invocation of the map() method -- only their contents are changed (by the reader's 
next() method). This can be a surprise to users, who might expect keys and vales to be 
immutable. This causes prolems when a reference to a key or value object is retained 
outside the map() method, as its value can change without warning. If you need to do 
this, make a copy of the object you want to hold on to. For example, for a Text object, 
you can use its copy constructor: new Text(value). 

The situation is similar with reducers. In this case, the value object in the reducer's 
iterator are reused, so you need to copy any that you need to retain between calls to 
the iterator. 
+0

あなたの答えは混乱しています。まず、「減速機はすべての値をメモリに格納しません」ということは、Iterableが必要に応じて値をロードすることを意味します。後で、「値リストのインスタンスが1つでもメモリよりも大きくなる可能性があります」ということは、値リストが最初にメモリに読み込まれることを意味します。あなたは明確にしていただけますか? – Zach

+0

編集して明確にします。私はちょうど単一の価値が大きいかもしれないことを意味しました。これは起こりそうもない。 「減速機はすべての値を記憶していません」というのは真実です。それは理にかなっていますか? –

+0

はい。説明をありがとうございます。あなたはこれを参考にしていますか? – Zach

2

それは、メモリ内で完全ではありません、それのいくつかは、コードを見て、ディスクから来ているフレームワークは、セグメントに反復処理可能を破るように思えるし、それらを一つのメモリ1にディスクを形成するロード。

org.apache.hadoop.mapreduce.task.ReduceContextImpl org.apache.hadoop.mapred.BackupStore

+0

問題の解決方法を教えてください。 –

0

他のユーザーによって引用されたとして、全体のデータがメモリにロードされていませんでした。 Apache documentation linkのmapred-site.xmlパラメータの一部を見てください。

mapreduce.reduce.merge.inmem.threshold 

デフォルト値:1000です。これは、メモリ内マージプロセスのファイル数のしきい値です。

mapreduce.reduce.shuffle.merge.percent 

デフォルト値は0.66です。で定義されている、メモリ内マップ出力の格納に割り当てられた合計メモリに対するパーセンテージで表される、メモリ内マージが開始される使用しきい値。

mapreduce.reduce.shuffle.input.buffer.percent 

デフォルト値は0.70です。シャッフル中に最大ヒープサイズからマップ出力を格納するために割り当てられるメモリの割合。

mapreduce.reduce.input.buffer.percent 

デフォルト値は0です。削減中にマップ出力を保持するための最大ヒープサイズに対するメモリの割合。シャッフルが完了すると、メモリ内の残りのマップ出力は、リダクションが開始される前にこのしきい値よりも少なく消費されなければなりません。

mapreduce.reduce.shuffle.memory.limit.percent 

デフォルト値は0.25です。 1つのシャッフルが消費できるメモリ内の制限の最大パーセンテージ