我正在寫一個MapReduce作業,最終可能會在reducer中產生大量的值。我擔心所有這些值都會一次加載到內存中。Hadoop Reducer內存中的值?
當需要時,Iterable<VALUEIN> values
的底層實現是否將值加載到內存中? Hadoop:權威指南似乎暗示了這種情況,但並沒有給出「確切的」答案。
減速機輸出將比輸入值大得多,但我相信輸出會根據需要寫入磁盤。
我正在寫一個MapReduce作業,最終可能會在reducer中產生大量的值。我擔心所有這些值都會一次加載到內存中。Hadoop Reducer內存中的值?
當需要時,Iterable<VALUEIN> values
的底層實現是否將值加載到內存中? Hadoop:權威指南似乎暗示了這種情況,但並沒有給出「確切的」答案。
減速機輸出將比輸入值大得多,但我相信輸出會根據需要寫入磁盤。
您正在正確閱讀本書。減速器不會將所有值存儲在內存中。相反,當循環遍歷Iterable值列表時,每個Object實例都會被重用,所以它只在給定的時間保持一個實例。
例如在下面的代碼中,objs ArrayList在循環後將具有預期的大小,但每個元素將是相同的b/c Text值實例在每次迭代中被重新使用。
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);
}
}
}
(如果由於某種原因,你也想借此每個VAL進一步的行動,你應該做一個深層副本,然後保存它。)
當然,即使單個值可能比內存大。在這種情況下,建議開發人員採取措施在先前的Mapper中削減數據,使其值不會太大。
UPDATE:請參閱Hadoop The權威指南第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.
這不是完全在內存中,有些是來自於磁盤,看代碼好像框架打破了Iterable成段,並加載它們由一種形式的磁盤到內存中1。
org.apache.hadoop.mapreduce.task.ReduceContextImpl org.apache.hadoop.mapred.BackupStore
你能解釋一下如何解決這個問題嗎? –
如引述的其他用戶,全部數據沒有被加載到存儲器中。看看Apache文檔鏈接中的一些mapred-site.xml參數。
mapreduce.reduce.merge.inmem.threshold
默認值:1000.它是根據內存合併過程的文件數閾值。
mapreduce.reduce.shuffle.merge.percent
默認值是0.66。啓動內存中合併的使用閾值,表示爲分配用於存儲內存中映射輸出的總內存的百分比,如mapreduce.reduce.shuffle.input.buffer.percent
所定義。
mapreduce.reduce.shuffle.input.buffer.percent
默認值是0.70。在洗牌過程中,從最大堆大小分配給存儲映射輸出的內存百分比。
mapreduce.reduce.input.buffer.percent
默認值爲0.相對於最大堆大小的內存百分比 - 在reduce期間保留映射輸出。當洗牌結束時,內存中任何剩餘的地圖輸出必須消耗小於此閾值才能開始減少。
mapreduce.reduce.shuffle.memory.limit.percent
默認值爲:0.25。單次洗牌可以消耗的內存限制的最大百分比
我很困惑你的答案。首先你說,「減速器不會將所有值存儲在內存中」,這意味着Iterable可以根據需要加載值。稍後,你會說,「甚至一個值列表的實例可能會比內存大,」這意味着值列表首先被加載到內存中。你能澄清一下嗎? – Zach
編輯澄清。我只是意味着即使是一個單一的價值可能很大。這不太可能。 「減速機不存儲所有的值」是一個真實的說法。那有意義嗎? –
是的。謝謝你的澄清。你有沒有參考這個,偶然? – Zach