解析大于hdfs块大小的XmlInputFormat元素

时间:2012-09-28 12:07:53

标签: java xml hadoop

我是Hadoop MapReduce的新手(确切地说是4天),我被要求在群集上执行分布式XML解析。根据我在互联网上的(重新)搜索,使用Mahout的XmlInputFormat应该相当容易,但我的任务是确保系统适用于大型(~5TB)XML文件。

据我所知,发送给映射器的文件拆分不能大于hdfs块大小(或每个作业块大小)。 [纠正我,如果我弄错的话。)

我面临的问题是一些XML元素很大(~200MB),有些很小(~1MB)

所以我的问题是:当XmlInputFormat创建的XML元素块大于块大小时会发生什么?它会将整个大文件(比方说200MB)发送给映射器还是将它发送出三个分区(64 + 64 + 64 + 8)?

我目前无法访问该公司的hadoop集群(并且不会在某个时间之前),所以我无法执行测试并找出答案。请帮助我。

1 个答案:

答案 0 :(得分:6)

所以要清楚一些事情:

Mahout的XMLInputFormat将处理XML文件并在两个配置的开始/结束标记之间提取XML。因此,如果您的XML如下所示:

<main>
  <person>
    <name>Bob</name>
    <dob>1970/01/01</dob>
  </person>
</main>

并且您已将开始/结束标记配置为<person></person>,然后您的映射器将通过以下<LongWritable, Text>对传递给其地图方法:

LongWritable: 10
Text: "<person>\n    <name>Bob</name>\n    <dob>1970/01/01</dob>\n  </person>"

您在映射器中对此数据执行的操作由您决定。

关于拆分,XmlInputFormat扩展TextInputFormat,所以如果您输入文件是可拆分的(即未压缩或使用可拆分编解码器(如snappy)压缩),则文件将由一个或多个地图制作者如下:

  1. 如果输入文件大小(比如48 MB)小于HDFS中的单个块(比方说64 MB),并且您没有配置最小/最大拆分大小属性,那么您将获得一个映射器处理文件
  2. 与上述相同,但您将最大拆分大小配置为10MB(mapred.max.split.size=10485760),那么您将获得5个映射任务来处理文件
  3. 如果文件大于块大小,那么您将获得每个块的地图任务,或者如果配置了最大分割大小,则按分割大小划分文件分区的每个部分的地图
  4. 当文件被拆分为这些块或拆分大小的块时,XmlInputFormat将寻找块/拆分边界的字节地址/偏移量,然后向前扫描,直到找到配置的XML开始标记或到达字节地址块/分割边界。如果它找到了开始标记,它将使用数据,直到找到结束标记(或文件结尾)。如果找到结束标记,则记录将传递给您的映射器,否则您的映射器将不会收到任何输入。要强调的是,在尝试查找结束标记时,地图可能会扫描块/拆分的末尾,但只有在找到开始标记时才会扫描,否则扫描会在块/拆分结束时停止。

    所以(最终)回答你的问题,如果你还没有配置映射器(并且正在使用默认或识别映射器,因为它也是已知的),那么是的,XML块的大小并不重要( MB,GB,TB!)它将被发送到减速器。

    我希望这是有道理的。

    修改

    跟进你的意见:

    1. 是的,每个映射器都会尝试处理文件的分割(字节范围)
    2. 是的,无论您设置的最大分割大小是什么,您的映射器都会收到代表开始/结束标记(包括)之间数据的记录。 person元素不会被分割而不管它的大小是什么(显然,如果在开始和结束元素之间存在GB的数据,你很可能会用尽内存来尝试将其缓冲到Text对象中)
    3. 从上面继续,你的数据永远不会在开始和结束元素之间分开,一个person元素将以其整体性发送给mapper,所以你应该总是可以使用类似SAX解析器的东西来进一步处理它不用担心你只看到人物元素的一部分。