2013-03-02 229 views
4

我有一個問題可以通過Hadoop Streaming以「typedbytes」或「rawbytes」模式解決,它允許用Java以外的語言分析二進制數據。 (如果沒有這些,Streaming會將某些字符(通常是\ t和\ n)解釋爲分隔符並抱怨非utf-8字符。將所有二進制數據轉換爲Base64會減慢工作流程,從而影響工作流程。這些二進制模式由HADOOP-1722添加。在調用Hadoop Streaming作業的命令行中,「-io rawbytes」可讓您將數據定義爲32位整數大小,然後是該大小的原始數據,「-io typedbytes」可讓您將數據定義爲1位零(意思是原始字節),接着是32位整數大小,接着是該大小的原始數據。我已經創建了這些格式的文件(帶有一個或多個記錄),並通過檢查typedbytes.py的輸出來驗證它們是否處於正確的格式。我也嘗試了所有可能的變化(大端,小端,不同的字節偏移等)。我正在使用Hadoop 0.20 from CDH4,它具有實現typedbytes處理的類,並且在設置「-io」開關時它正在輸入這些類。如何在Hadoop Streaming中使用「typedbytes」或「rawbytes」?

我使用「hadoop fs -copyFromLocal」將二進制文件複製到HDFS。當我嘗試將它用作map-reduce作業的輸入時,它會嘗試創建我指定長度的字節數組(例如3個字節)的行上發生OutOfMemoryError失敗。它必須錯誤地讀取數字並試圖分配一個巨大的塊。儘管如此,它確實設法向映射器(前一個記錄?不確定)獲取記錄,將其寫入標準錯誤以便我可以看到它。在記錄的起始處總是有太多字節:例如,如果文件是「\ x00 \ x00 \ x00 \ x00 \ x03hey」,則映射器將看到「\ x04 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x08 \ x00 \ x00 \ x00 \ x00 \ x03hey「(可重現的位,儘管沒有我能看到的模式)。

this talk的第5頁,我瞭解到有流式傳輸的「loadtb」和「dumptb」子命令,這些子命令在HDF中進行復制和在一個SequenceFile中打包/解開打包的字節。當與「-inputformat org.apache.hadoop.mapred.SequenceFileAsBinaryInputFormat」一起使用時,Hadoop會正確解包SequenceFile,但隨後會以完全相同的方式錯誤解釋包含在其中的typedbytes。

此外,我找不到這個功能的文檔。在2月7日(我通過電子郵件發送給自己)中,在streaming.html page on Apache中簡要提及,但是此r0.21.0網頁已被取消,the equivalent page for r1.1.1未提及rawbytes或typedbytes。

所以我的問題是:在Hadoop Streaming中使用rawbytes或typedbytes的正確方法是什麼?有沒有人得到它的工作?如果是這樣,有人可以發佈食譜嗎?對於希望在Hadoop Streaming中使用二進制數據的人來說,這似乎是個問題,而這應該是一個相當廣泛的羣體。

P.S.我注意到Dumbo,Hadoopyrmr都使用這個特性,但是應該有一種直接使用它的方法,不需要通過基於Python或基於R的框架來實現。

+0

「\ X04 \ X00 \ X00 \ X00 \ X00 \ X00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x08 \ x00 \ x00 \ x00 \ x00 \ x03hey「是一個長度爲(類型4),值爲0,後跟一個長度爲8 「\ X00 \ X00 \ X00 \ X00 \ x03hey」)。 這是一些typedbytes(0(類型),8(長度),字節)的編碼值。 – 2013-12-24 23:04:24

回答

4

好的,我發現了一個可行的組合,但它很奇怪。

  1. 在你的本地文件系統準備一個有效typedbytes文件,繼documentation或模仿typedbytes.py

  2. 使用

    hadoop jar path/to/streaming.jar loadtb path/on/HDFS.sequencefile < local/typedbytes.tb 
    

    包裹typedbytes在SequenceFile並把它放在HDFS,一步到位。

  3. 使用

    hadoop jar path/to/streaming.jar -inputformat org.apache.hadoop.mapred.SequenceFileAsBinaryInputFormat ... 
    

    運行圖,減少工作中的映射器從SequenceFile獲取輸入。請注意,-io typedbytes-D stream.map.input=typedbytes而不是被使用---明確要求typedbytes導致我在我的問題中描述的曲解。但是不要擔心:Hadoop Streaming會將輸入分割爲二進制記錄邊界而不是其'\ n'字符。中的數據由「\噸」和「\ N」分離出的映射器爲「RAWDATA」到達時,是這樣的:

    1. 32位帶符號整數,代表長度(注意:無類型字符)
    2. 塊原始二進制與長度:這是關鍵
    3. 「\ T」(製表符...爲什麼?)
    4. 32位帶符號整數,表示長度的原始二進制與長度的
    5. 塊:此是值
    6. '\ n'(換行符...?)
  4. 如果你想從另外發送映射原始數據減速,加

    -D stream.map.output=typedbytes -D stream.reduce.input=typedbytes 
    

    您的Hadoop命令行和格式化映射器的輸出和減速的預期輸入爲有效typedbytes。它們也爲鍵值對交替使用,但是這次使用的是字符型而不是'\ t'和'\ n'。 Hadoop Streaming正確地將這些配對按其鍵分割到二進制記錄邊界和組中。

stream.map.outputstream.reduce.input唯一的文檔,我能找到是在HADOOP-1722交換,從2月6日09(前面的討論中認爲不同的方式來參數化格式。)

這個配方不爲輸入提供強類型:在創建SequenceFile並用-inputformat解釋它的過程中,類型字符在某處丟失。但是,它確實提供了在二進制記錄邊界處的分裂,而不是'\ n',這是非常重要的事情,並且在映射器和縮減器之間的強打字。

+0

爲了清楚起見,至少在hadoop 2.0.0-cdh4.2.0中,「原始二進制數據」塊實際上是typedbytes本身(即類型字節,長度,然後是數據)。剛纔這讓我有點困惑。 – Dougal 2013-07-15 18:54:29

+0

如果您的typedbytes文件包含「\ n」,它是否仍然有效?你有沒有得到確切的字節,或者它被改變了? – 2013-10-09 11:24:50

+0

你得到確切的字節,包裹在一些額外的字節中,其目的我不明白。 「\ t」和「\ n」包含在Hadoop提供給您的映射器(而不是reducer,這是一系列不同的字節)---在您未修改的字節之前和之後。您不會將額外的字節添加到發送給'loadtb'的類型字節中。你給'loadtb'的東西完全符合規範。 – 2013-10-09 15:20:11

1

我們解決了二進制數據問題,使用hexancoding在分流級數據流數據到映射器。這可以利用並提高操作的並行效率,而不是在節點上處理之前首先轉換數據。

+0

感謝您的評論。在研究typedbytes之前,我正在進行base64的流式轉換(這是我想你所描述的:「hexaencoding」?)。我試圖避免所有的轉換,以便可以按原樣獲取一塊二進制數據。 – 2013-09-24 15:01:58

+0

Jim,僅供參考,@ ratang2000只是拼寫錯誤:它只是十六進制編碼,意思是將字節轉換爲十六進制字符串。這與Base64編碼不同。他使用的方式與此處提到的相同:https://issues.apache.org/jira/browse/HADOOP-1722。 – Subfuzion 2014-03-07 18:27:50

相關問題