从MapReduce映射器中的输入文件中获取唯一的行号

时间:2015-04-22 01:58:56

标签: java hadoop mapreduce line-numbers

我在HDFS中复制了一个包含1000万行的文件。需要在mapper中处理行号5000到500000。我该怎么做?

我尝试在mapper中覆盖run()方法并在那里尝试了一个计数器。但是当文件被拆分并且多个映射器正在运行时,当然会有多个计数器在运行。所以它没有帮助。粘贴下面的代码。

@Override
public void run(Mapper<LongWritable, Text, Text, Text>.Context context)
        throws IOException, InterruptedException {

    setup(context);

    Integer counter = 0;
    while (context.nextKeyValue()) {

        LongWritable currentKey = context.getCurrentKey();
        Text currentValue = context.getCurrentValue();

        System.out.println(currentKey.toString());

        map(currentKey, currentValue, context);
        counter++;
    }

    System.out.println("Counter: " + counter + " Time: "
            + System.currentTimeMillis());
}

此外,我在mapper中获得的KEY不是行号,而是行的偏移量。我们可以让KEY指向行号吗?如果是这样,它会在多个映射器中是唯一的吗? (当前KEY,偏移量,在映射器中不是唯一的。)

我怎样才能做到对不对?

2 个答案:

答案 0 :(得分:2)

  • 默认的InputFormats(如TextInputFormat)将给出记录的字节偏移量而不是实际的行号 - 这主要是由于在输入文件可拆分并由处理时无法确定真实的行号两个或更多的地图制作者。

  • 您可以创建自己的InputFormat来生成行号而不是字节偏移,但是您需要配置输入格式以从isSplittable方法返回false(大型输入文件不会被多个映射器处理)。如果您有小文件或大小接近HDFS块大小的文件,那么这不是问题。

  • 您还可以使用pig来清理数据并获取特定感兴趣的行并处理该特定数据。

    我觉得这是Hadoop的缺点,当您希望在不同系统之间共享全局状态时,Hadoop会失败。

答案 1 :(得分:0)

我会尝试在第一个MapReduce作业中添加这些行号。然后,您可以执行MapReduce作业,包括在Mapper中执行一些负责检查行号的代码,以便丢弃整行或执行分析。

修改 我现在认为第一个MR作业无法实现,因为映射器上的问题将与原始问题相同:它们将接收分裂而没有任何关于其位置的引用。整个大文件。