如何使用;typedbytes";或;“原始字节”;在Hadoop流媒体中?

如何使用;typedbytes";或;“原始字节”;在Hadoop流媒体中?,hadoop,binary,streaming,Hadoop,Binary,Streaming,我有一个问题可以通过Hadoop以“typedbytes”或“rawbytes”模式进行流处理来解决,它允许人们用Java以外的语言分析二进制数据。(如果不这样做,流式处理会将某些字符(通常为\t和\n)解释为分隔符,并抱怨非utf-8字符。将所有二进制数据转换为Base64会降低工作流速度,从而无法达到此目的。) 这些二元模式是由。在调用Hadoop流作业的命令行上,“-io rawbytes”允许您将数据定义为32位整数大小,后跟该大小的原始数据,“-io typedbytes”允许您将数据

我有一个问题可以通过Hadoop以“typedbytes”或“rawbytes”模式进行流处理来解决,它允许人们用Java以外的语言分析二进制数据。(如果不这样做,流式处理会将某些字符(通常为\t和\n)解释为分隔符,并抱怨非utf-8字符。将所有二进制数据转换为Base64会降低工作流速度,从而无法达到此目的。)

这些二元模式是由。在调用Hadoop流作业的命令行上,“-io rawbytes”允许您将数据定义为32位整数大小,后跟该大小的原始数据,“-io typedbytes”允许您将数据定义为1位零(即原始字节),后跟32位整数大小,后跟该大小的原始数据。我已经用这些格式创建了文件(有一个或多个记录),并通过与的输出进行检查来验证它们的格式是否正确。我还尝试了所有可能的变化(大端、小端、不同的字节偏移量等)。我使用的是Hadoop,它有实现typedbytes处理的类,当设置“-io”开关时,它会输入这些类


我使用“hadoop fs-copyFromLocal”将二进制文件复制到HDFS。当我尝试将其用作map reduce作业的输入时,它会失败,并在尝试生成我指定长度的字节数组(例如3字节)的行上出现OutOfMemoryError。它一定是读取错误的数字,并试图分配一个巨大的块代替。尽管如此,它还是设法将一条记录写入映射器(前一条记录?不确定),映射器将其写入标准错误以便我可以看到它。在记录的开头总是有太多字节:例如,如果文件是“\x00\x00\x00\x00\x03hey”,映射程序将看到“\x04\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x08\x00\x00\x00\x03hey”(可复制位,尽管我看不到模式)

从的第5页,我了解到流式处理有“loadtb”和“dumptb”子命令,它们一步复制到HDFS或从HDFS复制,并在SequenceFile中包装/展开键入的字节。当与“-inputformat org.apache.hadoop.mapred.SequenceFileAsBinaryInputFormat”一起使用时,hadoop正确地解压了SequenceFile,但随后以完全相同的方式误解了其中包含的typedbytes

此外,我找不到有关此功能的文档。在2月7日(我给自己发了一封电子邮件),它在中被简要提及,但这个r0.21.0网页后来被删除,没有提到rawbytes或typedbytes

所以我的问题是:在Hadoop流媒体中使用rawbytes或typedbytes的正确方法是什么?有人用过吗?如果是这样的话,有人能发布一份食谱吗?对于任何想在Hadoop流媒体中使用二进制数据的人来说,这似乎是一个问题,这应该是一个相当广泛的群体


另外,我注意到,所有人都使用了这个功能,但是应该有一种直接使用它的方法,而不需要通过基于Python或基于R的框架进行调解。

好的,我发现了一种有效的组合,但它很奇怪

  • 在本地文件系统中准备一个有效的typedbytes文件,遵循或模仿

  • 使用

    hadoop jar path/to/streaming.jar loadtb path/on/HDFS.sequencefile < local/typedbytes.tb
    
    hadoop jar path/to/streaming.jar -inputformat org.apache.hadoop.mapred.SequenceFileAsBinaryInputFormat ...
    
    运行映射程序从SequenceFile获取输入的map reduce作业。请注意,不应使用
    -io typedbytes
    -D stream.map.input=typedbytes
    ——明确要求typedbytes会导致我在问题中描述的误解。但不要担心:Hadoop流媒体在其二进制记录边界而不是“\n”字符上拆分输入。数据以“\t”和“\n”分隔的“rawdata”形式到达映射器,如下所示:

  • 32位有符号整数,表示长度(注意:无类型字符)
  • 具有该长度的原始二进制块:这是密钥
  • “\t”(制表符…为什么?)
  • 32位有符号整数,表示长度
  • 具有该长度的原始二进制块:这是值
  • “\n”(换行符…?)
  • 如果要将原始数据从映射器另外发送到reducer,请添加

    -D stream.map.output=typedbytes -D stream.reduce.input=typedbytes
    
    将映射器的输出和reducer的预期输入格式化为有效的typedbytes。它们也交替用于键值对,但这次使用类型字符,而不使用“\t”和“\n”。Hadoop流正确地在二进制记录边界上拆分这些对,并按键分组

  • 我能找到的关于
    stream.map.output
    stream.reduce.input
    的唯一文档是从2009年2月6日开始的exchange。(前面的讨论考虑了一种不同的格式参数化方法。)


    此方法不提供强输入:在创建序列文件并使用
    -inputformat
    解释它的过程中,类型字符丢失在某个地方。但是,它确实提供了二进制记录边界上的拆分,而不是真正重要的“\n”,以及映射器和还原器之间的强类型。

    我们在将数据向下传输到映射器时,在拆分级别对数据进行六进制编码,从而解决了二进制数据问题。这将利用并提高操作的并行效率,而不是在节点上处理之前先传输数据

    显然有一个用于流媒体的JustBytes IO模式的补丁,它将整个输入文件提供给mapper命令:


    为了清楚起见,至少在hadoop 2.0.0-cdh4.2.0中,“原始二进制数据”块实际上是typedbytes本身(即类型字节、长度,然后是数据)。这刚才让我有点困惑。如果您的typedbytes文件包含“\n”,它还能工作吗?你得到的是确切的字节还是经过了某种修改?你得到的是确切的字节,用一些我不理解的附加字节包装。“\t”和“\n”ar