如何设计MapReduce模型以合并两个文本文件

时间:2015-02-17 05:20:35

标签: hadoop merge mapreduce

例如,我有两个文件,A和B.它们都是文本文件。

A包含一行文字,如下所示:

I'm A

B包含三行文字:

I'm B1
I'm B2
I'm B3

我的例外是将A的唯一一行添加到B的每一行的前面,结果将是:

I'm A I'm B1
I'm A I'm B2
I'm A I'm B3

对我来说,困难的部分是如何理解MapReduce作业的参数。在传统的函数中,我可以让A和B成为两个参数,然后在我的规则中合并它们。一些像这样的伪代码:

// Two parameters, A and B
public void merge(File A, File B) {
    String lineA = A.firstLine;
    for (Each lineB in B) {
        String result = lineA + " " + lineB;
        File.wirte(result, "ResultFile", appended);
    }
}

但是在MapReduce阶段,没有"传统参数",例如:

public void map(LongWritable key, Text value, Context context) {
    String line = value.toString();
    try {
        context.write(new Text(line), new Text(""));
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

据我所知,上面的代码会逐行读取文件,使用每一行作为键并将值设置为空,然后将键值对写入文件。

但同样,上面的映射器代码没有传统的参数,我不知道如何执行合并字符串的逻辑,并将结果写出来。

以下是我现在想到的伪代码,我的设计是正确的还是我的方向错误?我该如何设计MapReduce作业?一些示例代码将非常有用!

// I think I should pass in two Files
// So I can merge the line of them
public void map(File A, File B, Context context) {
    String key = A.firstLine();
    for (each LineB in B) {
        String value = key + " " + lineB;
    }
    try {
        context.write(new Text(""), value);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

1 个答案:

答案 0 :(得分:0)

这是一个交叉连接 - 将A中的每条记录连接到B中的每条记录。幸运的是,这是一个很好的MapReduce设计模式。

解决方案取决于数据集的大小。如果A或B可以适合记忆,那么你很幸运。只需将它们中的任何一个添加到DistributedCache中,只将另一个读入映射器。你甚至不需要减速器!

如果两个数据集都很大,那么您的解决方案必须涉及编写自定义输入拆分,以确保每组数据输出足够的时间以匹配来自另一组的所有块。请参阅Cross product in MapReduce - 此示例也包含在MapReduce设计模式一书中。