【问题标题】:Aggregating a huge list from reducer input without running out of memory从减速器输入聚合一个巨大的列表而不会耗尽内存
【发布时间】:2017-05-12 18:46:56
【问题描述】:

在减少阶段(减少百分比的 67%),我的代码在尝试完成数小时后最终卡住并失败。我发现问题是reducer正在接收大量无法处理的数据并最终耗尽内存,从而导致reducer卡住。

现在,我正在尝试解决这个问题。目前,我正在根据 reducer 从每个键接收到的值组装一个列表。在减少阶段结束时,我尝试在列表中写入键和所有值。所以我的问题是,如何在不耗尽内存的情况下获得与该键相关的键和值列表的相同功能?

public class XMLReducer extends Reducer<Text, Text, Text, TextArrayWritable> {
private final Logger logger = Logger.getLogger(XMLReducer.class);

@Override
public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
    //logger.info(key.toString());
    Set<String> filesFinal = new HashSet<>();
    int size = 0;
    for(Text value : values) {
        String[] files = value.toString().split(",\\s+");
        filesFinal.add(value.toString());
        //size++;
    }
    //logger.info(Integer.toString(size));
    String[] temp = new String[filesFinal.size()];
    temp = filesFinal.toArray(temp);
    Text[] tempText = new Text[filesFinal.size()];
    for(int i = 0; i < filesFinal.size(); i++) {
        tempText[i] = new Text(temp[i]);
    }               
}
}

而 TextArrayWritable 只是将数组写入文件的一种方式

【问题讨论】:

    标签: list hadoop memory collections mapreduce


    【解决方案1】:

    您可以尝试通过编写自定义分区器来减少单个 reducer 读取的数据量。

    HashPartitioner 是 map reduce 作业使用的默认分区器。虽然这保证了您的均匀分布,但在某些情况下,很可能许多键被散列到单个 reducer。结果,与其他减速器相比,单个减速器将拥有大量数据。就你而言,我认为这是问题所在。

    解决这个问题:

    1. 分析您的数据和分组依据。你
    2. 尝试根据您的组键为您的自定义分区器提供分区功能。尝试限制每个分区的键数。

    您会看到工作中减少任务的数量有所增加。如果问题与不均匀的密钥分配有关,我提出的解决方案应该可以解决您的问题。

    您也可以尝试增加 reducer 内存。

    【讨论】:

    • 抱歉,最近几天没检查stackoverflow的其他问题。这并没有解决我的问题,因为我每个键都获得了太多数据。这意味着分区程序无法解决此问题。我尝试实现一种自定义流输出格式,它解决了必须将值存储在内存中的问题。不过到目前为止,我不太确定如何消除输出中的重复项
    猜你喜欢
    • 2016-12-25
    • 2021-02-10
    • 1970-01-01
    • 2016-08-01
    • 1970-01-01
    • 2023-03-08
    • 2011-11-10
    • 1970-01-01
    • 2021-06-04
    相关资源
    最近更新 更多