2012-09-28 98 views
1

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

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

我现在面临的问题是,一些XML元素都很大(〜200MB)和一些小(〜1MB)

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

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

回答

6

所以要明确出头了:

亨利马乌的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>" 

你在你的mapper中使用这些数据是由你自己决定的。

至于分裂,XmlInputFormat延伸TextInputFormat,因此,如果您输入文件是分割型(即未压缩的或具有可分离的编解码器,例如活泼的压缩),则该文件将被通过一个或多个映射器如下处理:

  1. 如果输入文件大小(假设48 MB)小于HDFS单块(可以说64MB),而且没有配置最小/最大分大小的属性,那么你会得到一个单个映射器来处理文件
  2. 与上面一样,但您将最大分割大小配置为10MB(mapred.max.split.size=10485760),那么您将得到5个映射任务来处理文件
  3. 如果文件大于块大小,那么您将为每个块获得一个映射任务,或者如果配置了最大分割大小,则将按该分割大小映射文件分割的每个部分

当文件被拆分成这些块或拆分大小的块时,XmlInputFormat将寻找块/拆分边界的字节地址/偏移量,然后向前扫描,直到找到配置的XML开始标记或达到字节块/拆分边界的地址。如果它找到开始标记,它将消耗数据直到找到结束标记(或文件结束)。如果它发现结束标记,记录将传递给你的映射器,否则你的映射器将不会收到任何输入。要强调的是,当试图找到结束标记时,地图可能会扫描块/分割的结尾,但只有在找到开始标记时才会执行此操作,否则将在块/分割结束时停止扫描。如果你还没有配置映射器(并且正在使用默认或标识映射器,因为它也是已知的),那么对于(最终)回答你的问题,那么是的,无论XML块有多大都不重要(MB的,GB的,TB的!)它将被发送到减速器。

我希望这是有道理的。

编辑

要跟进您的意见:

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

感谢您的回答。所以,让我说出我的理解,并请纠正我,如果我错了.. 1. XmlInputFormat将扫描XML元素,无论分裂。 2.除非我明确设置'mapred.max.split.size',否则它将发送整个元素(所有数据在之间),而不管它的大小 - 即使它是500 MB。 3.如果我设置了'mapred.max.split.size',它将拆分XML元素并将其发送给不同的映射器,但是因为这些块都不是完整的XML,所以它们不能通过StAX进行分析。 我正确以上3点? –

+0

@ChrisWhite能否澄清一些问题:由于'XMLInputFormat'扩展了'TextInputFormat',并且不覆盖'getSplits'方法,因此它使用'FileInputFormat'中的默认getSplits实现。如果我添加了根据XML标记进行拆分的自定义getSplits实现,它会使我受益吗?例如:https://github.com/whym/wikihadoop#splitting – Nilesh