我刚刚开始为开放街道Map数据开发一个基于hadoop的摄取器。有几种格式-但我一直针对基于protocolbuffer的格式(注意-它不是纯pb)。
在我看来,将文件预拆分为序列文件会更有效—而不是以自定义记录读取器/输入格式处理可变长度编码—但需要进行健全性检查。
格式在pbf format description中有更详细的描述,但基本上它是[blobheader,blob]块的集合。
有一个水滴头
message BlobHeader {
required string type = 1;
optional bytes indexdata = 2;
required int32 datasize = 3;
}
然后是blob(其大小由标头中的datasize参数定义)
message Blob {
optional bytes raw = 1; // No compression
optional int32 raw_size = 2; // Only set when compressed, to the uncompressed size
optional bytes zlib_data = 3;
// optional bytes lzma_data = 4; // PROPOSED.
// optional bytes OBSOLETE_bzip2_data = 5; // Deprecated.
}
很明显,一旦深入到blob中,就会有更多的结构——但我会在mapper中处理这个问题——我想做的是,最初每个mapper有一个blob(稍后可能是每个mapper blob的倍数)。
其他一些输入格式/记录读取器使用“足够大”的拆分大小,然后向后/向前查找分隔符-但是由于没有分隔符可以让我知道blob/headers的偏移量-也没有指向它们的索引-我看不到任何方法来获取拆分点,而不首先对文件进行流式处理。
现在,我不需要从磁盘上读取整个文件—我可以从读取头开始,使用该信息查找blob,将其设置为第一个分割点,然后重复。但这是我能想到的唯一一个可以替代预分割成序列文件的方法。
有没有更好的方法来处理这个问题?如果没有,对这两个建议有什么想法?
1条答案
按热度按时间toiithl61#
好吧,我用getsplits方法解析二进制文件——由于跳过了99%以上的数据,所以速度非常快(planet osm 22gb world文件大约20秒)。如果其他人遇到了问题,下面是getsplits方法。
工作良好,迄今为止-虽然我还没有地面truthed输出尚未。它肯定比将pbf复制到hdfs、在一个Map器中转换成一个序列,然后摄取(复制时间占主导)要快得多。它也比在hdfs中使用外部程序拷贝到序列文件,然后针对hdfs运行Map程序(后者编写脚本)快20%。所以这里没有抱怨。
请注意,这将为每个块生成一个Map器,即行星世界文件的~23kMap器。实际上,我是在每次拆分时捆绑多个块—只需在拆分添加到集合之前循环x次。
对于blobheader,我刚刚从上面的osmwiki链接编译了protobuf.proto文件。如果需要,也可以从osm二进制类中提取预生成的-maven片段是: