2012-10-07 5 views
6

マッパー出力の一部を、たとえばHDFSのフォルダAなどのフォルダに書きたいと思います。出力の他の部分は、私はそれを減速機で処理したい。これは可能ですか?私は複数の出力を知っています。これは複数の出力を使用して可能ですか?ハーフープでHDFSに他の部分を書き込むだけで、マッパーの部分をレデューサーに送ることは可能ですか?

ありがとうございます!

答えて

6

はいドキュメントによると、マップステージでMultipleOutputs経由で渡された出力は、レデューサーによって無視されるため、MultipleOutputsで行うことができます。これはまさにあなたが望むものです。私はmy GitHubの小さな例を書いています。それが役に立つと願っています。

+0

返信いただきありがとうございます!私はそれを試して、それは動作します! –

1

あなたは自分のマッパーの実装からHDFSへの直接出力を書き込むことができます - ただ、コンテキストのコンフィギュレーションを使用して、ファイルシステムオブジェクトを作成し、ファイルを作成し、そこに書いて、それを閉じることを忘れないでください:

public void cleanup(Context context) { 
    FileSystem fs = FileSystem.get(context.getConfiguration()); 
    PrintStream ps = new PrintStream(fs.create(
     new Path("/path/to/output", "map-output"))); 
    ps.println("test"); 
    ps.close(); 
} 
その他

考慮すべき点 - 各ファイルはHDFSで一意に命名される必要があるため、ファイル名にマッパーID番号を付けることができますが、投機的な実行も考慮する必要があります(マッパータスクインスタンスは2つの場所HDFS内の同じファイルに書き込む)。

出力コミッターはタスクIDと試行番号を持つtmp HDFSディレクトリにファイルを作成し、そのタスク試行のコミット時に正しい場所とファイル名に移動するだけです。推測的な実行をオフにしたり、HDFSで複数のファイルを作成したりせずにマップ側(ローカルファイルシステムにデータが書き込まれる)を実行すると、この問題は回避できません。

ので、より多くの「完全な」ソリューションは、次のようになります。

FileSystem fs = FileSystem.get(context.getConfiguration()); 
PrintStream ps = new PrintStream(fs.create(new Path(
     "/path/to/output", String.format("map-output-%05d-%d", 
     context.getTaskAttemptID().getTaskID().getId(), 
     context.getTaskAttemptID().getId())))); 
ps.println("test"); 
ps.close(); 

MultipleOutputsあなたが側を減らすのに役立つだろうが、私は何も出力コミッターと仕事がないように、マップ側はそれがうまくいくとは思いませんディレクトリがHDFSにありません。

もちろん、これがマッパーだけのジョブであれば、MultipleOutputsが機能します。だから、別のアプローチは、マップのみのジョブを実行して、(アイデンティティマッパーを使用して)セカンダリジョブで出力の目的の部分を使用することです - あなたが推測する移動量に依存します。

+0

こんにちは、クリス!返信いただきありがとうございます!私は、マッパーで複数の出力ロジックを実装しようとしました。 output.collectを使用して送信したものは、レデューサーに送信されるだけです。別のフォルダに複数の出力を使用して書き込む出力は、私が確認した限り、減速機に送られません。このタイプの実装をプロジェクトに使用できますか?そうすることに欠点はありますか? –

+0

私はあなたのコメントを完全に理解しているかどうかはわかりませんが、試したことがあなたのために働いていれば、それを使用してください。 –

+0

返信いただきありがとうございます! –

関連する問題