使用hadoop流写入不同的文件

时间:2011-09-27 06:09:16

标签: hadoop hadoop-streaming

我目前正在10台服务器hadoop集群上处理大约300 GB的日志文件。我的数据保存在名为YYMMDD的文件夹中,因此每天都可以快速访问。

我的问题是我今天刚刚发现我的日志文件中的时间戳是DST(GMT -0400),而不是预期的UTC。简而言之,这意味着logs / 20110926 / * .log.lzo包含2011-09-26 04:00到2011-09-27 20:00之间的元素,它几乎毁掉了对该数据所做的任何map / reduce(即生成统计数据)。

有没有办法执行map / reduce作业以正确地重新分割每个日志文件?据我所知,似乎没有办法使用流式传输在输出文件A中发送某些记录,而在输出文件B中发送其余记录。

这是我目前使用的命令:

/opt/hadoop/bin/hadoop jar /opt/hadoop/contrib/streaming/hadoop-streaming-0.20.2-cdh3u1.jar \
-D mapred.reduce.tasks=15 -D mapred.output.compress=true \
-D mapred.output.compression.codec=com.hadoop.compression.lzo.LzopCodec \
-mapper map-ppi.php -reducer reduce-ppi.php \
-inputformat com.hadoop.mapred.DeprecatedLzoTextInputFormat \
-file map-ppi.php -file reduce-ppi.php \
-input "logs/20110922/*.lzo" -output "logs-processed/20110922/"

我对Java和/或创建自定义类一无所知。我确实尝试了在http://blog.aggregateknowledge.com/2011/08/30/custom-inputoutput-formats-in-hadoop-streaming/发布的代码(几乎复制/粘贴了那里的内容),但我根本无法让它工作。无论我尝试什么,我都会得到一个“-outputformat:class not found”错误。

非常感谢您的时间和帮助:)。

2 个答案:

答案 0 :(得分:1)

  

据我所知,似乎没有办法使用流式传输在输出文件A中发送某些记录,而在输出文件B中发送其余记录。

通过使用自定义Partitioner,您可以指定哪个键转到哪个reducer。默认情况下,使用HashPartitioner。看起来唯一的其他Partitioner Streaming支持是KeyFieldBasedPartitioner

您可以在Streaming here的上下文中找到有关KeyFieldBasedPartitioner的更多详细信息。您无需了解Java即可使用Streaming配置KeyFieldBasedPartitioner。

  

有没有办法执行map / reduce作业以正确地重新分割每个日志文件?

您应该能够编写MR作业来重新拆分文件,但我认为Partitioner应该解决问题。

答案 1 :(得分:0)

自定义MultipleOutputFormat和Partitioner似乎是按天分割数据的正确方法。

作为那篇文章的作者,抱歉你有这么艰难的时光。听起来如果你收到“找不到类”的错误,那么在你用“-libjars”包含它后,你的自定义输出格式就找不到了。