5

S3にはスナップ圧縮されたサーバーログがたくさんあり、ElasticMapReduceでストリーミングを使用してそれらを処理する必要があります。ストリーミングマッパースクリプトに送信する前に解凍できるように、ログが(HFSにプルされる前に)すでに圧縮されていることをAmazonとHadoopに伝えるにはどうすればよいですか?

私が見つけることができる唯一のドキュメントはここにあります:http://docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/HadoopDataCompression.html#emr-using-snappy 、そしてそれは中間圧縮を参照しているようであり、 HFSに到着すると圧縮されます。

ところで、私は主にPythonで作業しているので、botoで解決策がある場合はボーナスポイントがあります!

4

2 に答える 2

7

答えは「できない」です。少なくとも、Hadoopの外部で発生するスナップ圧縮されたファイルにHadoopストリーミングを適用する特定のケースではありません。

私は(徹底的に!)この結論に到達するために2つの主なオプションを検討しました:(1)高度にカフェイン化されたものによって提案されたhadoopの組み込みのsnappy圧縮を使用することを試みるか、(2)snappyファイルを消費および解凍するために独自のストリーミングモジュールを作成します。

オプション(1)の場合、snappyを使用してファイルを圧縮すると、hadoopによってファイルにマークアップが追加されるようです。私のファイルはhadoopの外部でsnappyを使用して圧縮されているため、hadoopの組み込みコーデックはファイルを解凍できません。

この問題の症状の1つは、ヒープスペースエラーでした。

2013-04-03 20:14:49,739 FATAL org.apache.hadoop.mapred.Child (main): Error running child : java.lang.OutOfMemoryError: Java heap space
    at org.apache.hadoop.io.compress.BlockDecompressorStream.getCompressedData(BlockDecompressorStream.java:102)
    at org.apache.hadoop.io.compress.BlockDecompressorStream.decompress(BlockDecompressorStream.java:82)
    at org.apache.hadoop.io.compress.DecompressorStream.read(DecompressorStream.java:76)
    at java.io.InputStream.read(InputStream.java:85)
    ...

はるかに大きなインスタンスに切り替えてmap​​red.child.java.opts設定を上げると、新しいエラーが発生しました。

java.io.IOException: IO error in map input file s3n://my-bucket/my-file.snappy

Hadoopのスナッピーコーデックは、外部で生成されたファイルでは機能しません。

オプション(2)の場合、問題は、Hadoopストリーミングが\ n、\ r、および\ r\nの改行を区別しないことです。きびきびとした圧縮は、圧縮されたファイル全体にそれらのバイトコードをまき散らすことになりますので、これは致命的です。これが私のエラートレースです:

2013-04-03 22:29:50,194 WARN org.apache.hadoop.mapred.Child (main): Error running child
java.lang.RuntimeException: PipeMapRed.waitOutputThreads(): subprocess failed with code 1
    at org.apache.hadoop.streaming.PipeMapRed.waitOutputThreads(PipeMapRed.java:372)
    at org.apache.hadoop.streaming.PipeMapRed.mapRedFinished(PipeMapRed.java:586)
    at org.apache.hadoop.streaming.PipeMapper.close(PipeMapper.java:135)
    at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:57)
    ...

hadoopのJavaクラス(たとえば、ここを参照)を少し作業するだけで、\ r vs\nの問題を修正できる可能性があります。しかし、最初に言ったように、私の目標は、Javaに触れることなく、Hadoopストリーミングモジュール内に構築することでした。その制約があるため、この問題を解決する方法はないようです。

結局、私はこのクラスターが消費しているファイルを生成している人たちに戻って、gzipまたはlzoに切り替えるように説得しました。

PS-オプション(2)で、異なる文字(textinputformat.record.delimiter = Xなど)でレコードを分割して遊んでみましたが、非常にハッキーで、とにかく機能しませんでした。

PPS-別の回避策は、S3からファイルをダウンロードして解凍し、-copyFromLocalを実行してHDFSにプルするスクリプトを作成することです。計算上、これには何の問題もありませんが、ワークフローの観点からは、あらゆる種類の面倒が発生します。

于 2013-04-04T20:31:58.787 に答える
1

TextInputFormat(またはそのサブクラスの1つ)を使用していると仮定すると、拡張子が.snappyの圧縮された入力ファイルは自動的に処理されます。

snappyの代わりにlzo圧縮(.gz拡張)の使用を検討することをお勧めします。圧縮率を向上させるために圧縮速度をいくらかあきらめ、分割可能な入力ファイルを作成します。Clouderaはブログでこれについて言及しています:

注意すべき点の1つは、Snappyは、プレーンテキストで直接使用するのではなく、シーケンスファイルやAvroデータファイルなどのコンテナ形式で使用することを目的としていることです。後者は分割できず、で処理できないためです。 MapReduceを使用して並列化します。これはLZOとは異なります。LZOでは、LZO圧縮ファイルにインデックスを付けて分割点を決定し、LZOファイルを後続の処理で効率的に処理できるようにします。

于 2013-03-31T23:00:46.820 に答える