是否可以将对象的实例与一个文件关联,同时由仅映射的映射作业进行映射?

时间:2013-09-25 20:43:14

标签: java hadoop mapreduce accumulo

我想使用在映射时存在/对一个文件起作用的HashSet,然后在映射下一个文件时重置/重新创建。我已修改TextInputFormat以覆盖isSplitable以返回false,因此文件不会被拆分并由Mappers作为整体进行处理。可以这样做吗?或者是否有另一种方法可以减少对Accumulo表的写入?

让我先说我不相信我想要一个全局变量。我只是想确保唯一性,从而减少我的Accumulo表中的突变。

我的项目是将分片示例中的Index.java文件的功能从线性accumulo客户端程序转换为使用mapreduce功能的程序,同时仍在Accumulo中创建相同的表。它需要mapreduce,因为这是流行语,实质上它比线性程序运行速度快于数TB的数据。

以下是索引代码供参考: http://grepcode.com/file/repo1.maven.org/maven2/org.apache.accumulo/examples-simple/1.4.0/org/apache/accumulo/examples/simple/shard/Index.java

该程序使用BatchWriter将Mutations写入Accumulo,并在每个文件的基础上进行。为了确保它不会写出超过必要的更多突变并确保唯一性(尽管我确实认为Accumulo最终通过压缩合并相同的键),Index.java有一个HashSet,用于确定之前是否运行过一个单词。这一点都比较容易理解。

转移到仅限地图的mapreduce作业更复杂。

这是我对映射的尝试,这似乎与我见过的Accumulo表的部分输出有点相似,但与线性程序Index.java相比,运行真的很慢

public static class MapClass extends Mapper<LongWritable,Text,Text,Mutation> {
        private HashSet<String> tokensSeen = new HashSet<String>();
        @Override
        public void map(LongWritable key, Text value, Context output) throws IOException {
            FileSplit fileSplit = (FileSplit)output.getInputSplit();
            System.out.println("FilePath " + fileSplit.getPath().toString());
            String filePath = fileSplit.getPath().toString();
            filePath = filePath.replace("unprocessed", "processed");

            String[] words = value.toString().split("\\W+");

            for (String word : words) {
                Mutation mutation = new Mutation(genPartition(filePath.hashCode() % 10));
                word = word.toLowerCase();
                if(!tokensSeen.contains(word)) {
                    tokensSeen.add(word);
                    mutation.put(new Text(word), new Text(filePath), new Value(new byte[0]));
                }

                try {
                    output.write(null, mutation);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

慢的问题可能是我在测试实例上运行所有这一切,Hadoop的单节点实例,ZooKeeper和Accumulo在顶部。如果是这样的话,我只需找到一个独特的解决方案。

非常感谢您提供的任何帮助或建议。

1 个答案:

答案 0 :(得分:1)

Mapper具有setupcleanup方法,您可以覆盖这些方法以更干净地处理此类事情。 setup被调用一次,然后多次调用map(每个记录一次),然后在结束时调用cleanup一次。我们的想法是你在setup方法中创建HashSet,在map中构建它,并在cleanup中提交所有内容,或者定期刷新一些map的调用。 1}}如有必要。

但是,在移动到真正的集群之前,几乎肯定不会看到运行时有任何改进。单节点测试实例与简单的线性程序几乎没有任何好处,只要一旦获得真正的hadoop集群,相同的代码将运行得更快。