簡體   English   中英

Spark flatMap / reduce:如何縮放和避免OutOfMemory?

[英]Spark flatMap/reduce: How to scale and avoid OutOfMemory?

我正在將一些map-reduce代碼遷移到Spark中,並且在構造Iterable返回函數時遇到問題。 在MR代碼中,我有一個由鍵分組的reduce函數,然后(使用multipleOutputs)對值進行迭代,並使用寫入(在多個輸出中,但這並不重要)這樣的代碼(簡化):

reduce(Key key, Iterable<Text> values) {
    // ... some code
    for (Text xml: values) {
        multipleOutputs.write(key, val, directory);
    }
}

但是,在Spark中,我翻譯了地圖,並將其簡化為以下序列:mapToPair-> groupByKey-> flatMap,在某些書中建議...。

mapToPair基本上是通過functionMap添加一個Key,該鍵基於記錄上的某些值為該記錄創建一個Key。 有時,密鑰可能具有很高的基數。

JavaPairRDD<Key, String> rddPaired = inputRDD.mapToPair(new PairFunction<String, Key, String>() { 
    public Tuple2<Key, String> call(String value) {
        //... 
        return functionMap.call(value);
    }
});

rddPaired應用了RDD.groupByKey()以獲取RDD來提供flatMap函數:

JavaPairRDD<Key, Iterable<String>> rddGrouped = rddPaired.groupByKey();

分組后,flatMap調用執行reduce 在這里, 操作是一個轉換:

public Iterable<String> call (Tuple2<Key, Iterable<String>> keyValue) {
    // some code...
    List<String> out = new ArrayList<String>();
    if (someConditionOnKey) { 
        // do a logic
        Grouper grouper = new Grouper();
        for (String xml : keyValue._2()) {
            // group in a separate class
            grouper.add(xml);
        }
        // operation is now performed on the whole group
        out.add(operation(grouper));
    } else {
        for (String xml : keyValue._2()) {
            out.add(operation(xml));
        }
        return out;
    }
}

它的工作原理很好……使用沒有太多記錄的鍵。 實際上,當具有大量值的鍵在化簡中輸入“ else”時,它將被OutOfMemory中斷。

注意:我已經包括了“ if”部分來解釋我要產生的邏輯,但是失敗是在輸入“ else”時發生的……因為當數據輸入“ else”時,通常意味着會有更多的值由於數據的性質。

顯然,必須將所有分組值保留在“外”列表中,如果鍵具有數百萬條記錄,它將無法擴展,因為它將把它們保留在內存中。 我已經到了發生OOM的地步(是的,這是在執行上面的“操作”時需要內存的操作-沒有給出任何操作。盡管這不是很昂貴的內存操作)。

有什么辦法可以避免這種情況以擴展規模? 通過使用其他一些指令復制行為以更可擴展的方式達到相同的輸出,或者能夠派出Spark值進行合並(就像我以前對MR所做的那樣)...

flatMap操作中進行條件處理效率很低。 您應該檢查外部條件以創建2個不同的RDD並分別處理它們。

rddPaired.cache();

// groupFilterFunc will filter which items need grouping
JavaPairRDD<Key, Iterable<String>> rddGrouped = rddPaired.filter(groupFilterFunc).groupByKey();
// processGroupedValuesFunction should call `operation` on group of all values with the same key and return the result
rddGrouped.mapValues(processGroupedValuesFunction);

// nogroupFilterFunc will filter which items don't need grouping
JavaPairRDD<Key, Iterable<String>> rddNoGrouped = rddPaired.filter(nogroupFilterFunc);
// processNoGroupedValuesFunction2 should call `operation` on a single value and return the result
rddNoGrouped.mapValues(processNoGroupedValuesFunction2);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM