我刚刚开始学习hadoop,我想确认我对“如何将xml文件存储在hdfs中并由mappers处理”的理解。
我有一个xml文件,xml格式如下。它的简单customerlist xml示例。此文件的大小为1 gb。现在,如果我将这个文件移到hdfs中,它将被分割成16个块(如果我们将每个分割的默认块大小保持为64mb)。因此,将有16个Map程序来处理这个文件,每个块一个。
<?xml version="1.0"?>
<customerList>
<customer>
<id></id>
<name></name>
<age></age>
<address></address>
</customer>
<customer>
<id></id>
<name></name>
<age></age>
<address></address>
</customer>
...
...
现在,如果我理解正确的话,一个Map绘制者会认为每一项工作都是完整的 <customer></customer>
用于处理的标记可能会失败,因为使用 -put
或者 -copyFromLocal
不保证hdfs中的每个分割块都有 n
完成的数量 <customer></customer>
贴上标签。一些分裂块可能会结束如下。
...
...
<customer>
<id></id>
<name></name>
<age></age>
<address></address>
</customer>
<customer>
<id></id>
<name></name>
现在如果我们想确保每个区块都有一个完整的客户标签 <customer></customer>
,我们可以采用以下解决方案。
avro:将每个客户的xml转换成avro类型,比如记录类型,并使用avro serialize,把这个文件作为hdfs中的“avro data file”,支持拆分,可以保证一个块中有一个完整的avro记录。
序列文件:我不确定这个,但我认为我们可以标记同步点,同时创建一个序列文件,这是用来分裂成块的文件。在这里,我们可以标记每个客户标签的结尾 </customer>
'作为同步点,这将保证没有客户开始标记' <customer>
'将在同一块中没有结束标记。
有人能证实我的理解是否正确吗?除了这两个问题,还有别的解决办法吗。
2条答案
按热度按时间rsaldnfx1#
您的理解是正确的,因为Map器运行在从块而不是完整块派生的拆分上。所以Map绘制者肯定会更多。
因此,在xml文件的存储方面,它们将遵循序列化的概念进入hdfs,并在读取时进行反序列化(serdes),除了avro之外,还引入了其他serdes。比如节俭等等。
nqwrtyyt2#
记录不必是Map器的本地记录,只是出于性能原因,它更可取。大多数mapreduce输入格式都会搜索块的末尾,以完成块的最终记录。这会在进程中引入一些远程读取,但作为总读取的一部分,它通常非常低。
mahout xmlinputformat就是这样做的。每次运行时
next()
为了创建一个新的记录,它从最后一个完成点开始扫描,并且只有在确定下一个记录完全跨越分配给Map器的分割之外时才拒绝返回。