如何在Hadoop map / reduce中映射到映射器中的多个文件?

时间:2015-01-11 14:30:37

标签: java hadoop mapreduce hdfs parquet

我有一个map reduce作业,没有任何reducer解析输入文件,并在Parquet格式的映射器中的磁盘上写一些输出。 由于此作业可以将多个文件夹中的文件作为输入(每个日期一个文件夹),我还希望将输出拆分为文件夹,如:

01JAN15
    output-0000
    output-0001

02JAN15
    output-0000
    output-0001

我查看了documentation中的MultipleOutput格式类,但它似乎只能在reduce部分的几个文件夹中写入。

不知何故,写入同一目录中的多个文件可以正常工作,但是一旦我尝试在多个目录中写入,我就会得到一个异常(可能是因为有些映射器试图同时创建同一个目录?)。 / p>

仅供参考我的代码在mapper中看起来像那样:

mos.write("pb", null, message, date + "/output");

我定义了输出格式:

MultipleOutputs.addNamedOutput(job, "pb", ProtoParquetOutputFormat.class,
Void.class, com.google.protobuf.Message.class);

我得到的例外是:

15/01/11 15:05:09 WARN ipc.Client: interrupted waiting to send rpc request to server
java.lang.InterruptedException
    at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:400)
    at java.util.concurrent.FutureTask.get(FutureTask.java:187)
    at org.apache.hadoop.ipc.Client$Connection.sendRpcRequest(Client.java:1046)
    at org.apache.hadoop.ipc.Client.call(Client.java:1441)
    at org.apache.hadoop.ipc.Client.call(Client.java:1399)
    at org.apache.hadoop.ipc.ProtobufRpcEngine$Invoker.invoke(ProtobufRpcEngine.java:232)
    at com.sun.proxy.$Proxy9.getBlockLocations(Unknown Source)
    at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolTranslatorPB.getBlockLocations(ClientNamenodeProtocolTranslatorPB.java:254)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.hadoop.io.retry.RetryInvocationHandler.invokeMethod(RetryInvocationHandler.java:187)
    at org.apache.hadoop.io.retry.RetryInvocationHandler.invoke(RetryInvocationHandler.java:102)
    at com.sun.proxy.$Proxy10.getBlockLocations(Unknown Source)
    at org.apache.hadoop.hdfs.DFSClient.callGetBlockLocations(DFSClient.java:1220)
    at org.apache.hadoop.hdfs.DFSClient.getLocatedBlocks(DFSClient.java:1210)
    at org.apache.hadoop.hdfs.DFSClient.getLocatedBlocks(DFSClient.java:1200)
    at org.apache.hadoop.hdfs.DFSInputStream.fetchLocatedBlocksAndGetLastBlockLength(DFSInputStream.java:271)
    at org.apache.hadoop.hdfs.DFSInputStream.openInfo(DFSInputStream.java:238)
    at org.apache.hadoop.hdfs.DFSInputStream.<init>(DFSInputStream.java:231)
    at org.apache.hadoop.hdfs.DFSClient.open(DFSClient.java:1498)
    at org.apache.hadoop.hdfs.DistributedFileSystem$3.doCall(DistributedFileSystem.java:302)
    at org.apache.hadoop.hdfs.DistributedFileSystem$3.doCall(DistributedFileSystem.java:298)
    at org.apache.hadoop.fs.FileSystemLinkResolver.resolve(FileSystemLinkResolver.java:81)
    at org.apache.hadoop.hdfs.DistributedFileSystem.open(DistributedFileSystem.java:298)
    at org.apache.hadoop.fs.FileSystem.open(FileSystem.java:766)
    at parquet.hadoop.ParquetFileReader.readFooter(ParquetFileReader.java:272)
    at parquet.hadoop.ParquetFileReader$2.call(ParquetFileReader.java:180)
    at parquet.hadoop.ParquetFileReader$2.call(ParquetFileReader.java:176)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)

你知道我想做什么是可能的吗?我究竟做错了什么? 谢谢!

3 个答案:

答案 0 :(得分:0)

我知道,你的意思但不幸的是(根据我的知识)你需要自己做的

只需创建从Configured和Implementing Tool界面扩展的Driver类。然后你可以简单地配置一个在MapRed执行完成后调用的Callback,然后编写代码来移动各个文件夹中的文件。

这是链接

Callback after Mapred complets

答案 1 :(得分:0)

您可以使用分区输出到不同的文件中。

答案 2 :(得分:0)

输出文件不能由多个进程(映射器或缩减器)写入,因此为了生成多个输出文件,我要么必须定义自定义分区,要么将数据分组到reducer中并拥有键输出文件名。 无法通过映射器将多个输入文件中的数据写入同一文件中。