2

您好,我目前正在学习 Map Reduce,并正在尝试使用 hadoop 1.0.4 构建一个小型作业。我有一个停用词列表和一个模式列表。在我的文件被映射之前,我想将停用词加载到一个高效的数据结构中,比如地图。我还想从我的模式列表中构建一个正则表达式模式。由于这些是串行任务,我想在映射之前执行它们并为每个映射器传递一份副本那些他们可以读/写的对象。我想过在我的驱动程序类中简单地使用一个带有 getter 的静态变量,但是使用 java 调用对象作为指针原则这行不通。我当然可以在传递对象之前克隆它,但这似乎不是一个好习惯。我读了一些关于分布式缓存的东西,但据我了解,它只用于文件而不是对象,而且我可以让每个映射器读取停止词/模式文件。

谢谢你的帮助!

4

2 回答 2

2

一种可能的解决方案是在运行作业之前将 stopwords.txt 复制到 HDFS,然后在 Mapper 的setup方法中将其读入适当的数据结构。例如:

MyMapper 类:

...
private Map<String, Object> stopwords = null;

@Override
public void setup(Context context) {
    Configuration conf = context.getConfiguration();
    //hardcoded or set it in the jobrunner class and retrieve via this key
    String location = conf.get("job.stopwords.path");
    if (location != null) {
        BufferedReader br = null;
        try {
            FileSystem fs = FileSystem.get(conf);
            Path path = new Path(location);
            if (fs.exists(path)) {
                stopwords = new HashMap<String, Object>();
                FSDataInputStream fis = fs.open(path);
                br = new BufferedReader(new InputStreamReader(fis));
                String line = null;
                while ((line = br.readLine()) != null && line.trim().length() > 0) {
                    stopwords.put(line, null);
                }
            }
        }
        catch (IOException e) {
            //handle
        } 
        finally {
            IOUtils.closeQuietly(br);
        }
    }
}
...

然后,您可以在 map 方法中使用停用词。

另一种选择是在 jobrunner 类中使用停用词创建映射对象,将其序列化为 Base64 编码的字符串,将其作为 Configuration 对象中某个键的值传递给映射器,并在 setup 方法中对其进行反序列化。

我会选择第一个选项,不仅因为它更容易,而且因为通过 Configuration 对象传递大量数据并不是一个好主意。

于 2012-11-21T22:20:47.190 回答
2

Hadoop 分布式缓存是一种特定于将一些参考数据传递给映射器的机制。从性能的角度来看,它比从 HDFS 加载更好——因为数据将从 HDFS 传递到本地文件系统,每个节点一次,而不是每个任务一次。
您完全正确 - 它仅适用于文件和读取文件并将它们转换为您的数据结构是您的责任。
据我所知,hadoop 不支持传递对象。虽然如果您将在这些文件中使用某种序列化 - 它会接近您的要求。

于 2012-11-22T07:25:19.713 回答