当前位置: 首页 > 知识库问答 >
问题:

将snappy压缩文件加载到Elastic MapReduce中

戴浩初
2023-03-14

我在S3中有一堆快速压缩的服务器日志,我需要在Elastic MapReduce上使用流式处理它们。如何告诉Amazon和Hadoop日志已经被压缩(在它们被拉入HFS之前!)以便它们可以在发送到流式映射器脚本之前被解压缩?

我能找到的唯一文档是:http://docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/HadoopDataCompression.html#emr-使用snappy,似乎指的是中间压缩,而不是到达HFS时压缩的文件。

顺便说一句,我主要在python中工作,所以如果你在boto中有一个解决方案,那就加分!

共有2个答案

谭文林
2023-03-14

假设您使用的是TextInputFormat(或其子类之一),则会自动处理扩展名为. snappy的压缩输入文件。

您可能需要考虑使用lzo压缩(. gz扩展)而不是snappy。您放弃一些压缩速度以获得更好的压缩率和可拆分的输入文件。Cloudera在他们的博客中提到了这一点:

需要注意的一点是,Snappy旨在与容器格式一起使用,例如序列文件或Avro数据文件,而不是直接在纯文本上使用,例如,因为后者不可拆分,并且不能使用MapReduce并行处理。这与LZO不同,可以索引LZO压缩文件以确定拆分点,以便在后续处理中有效地处理LZO文件

庄文栋
2023-03-14

答案是,“这是不可能的。”至少在将hadoop流应用于源于hadoop之外的snappy压缩文件的特定情况下是不可能的。

我(彻底!)探索了两个主要选项来得出这一结论:(1)尝试使用HighlyCaffined建议的hadoop内置snappy压缩,或(2)编写自己的流模块来使用和解压缩snappy文件。

对于选项(1),hadoop似乎在使用snappy压缩文件时向文件添加了一些标记。由于我的文件是在hadoop外部使用snappy压缩的,hadoop的内置编解码器无法解压缩文件。

此问题的一个症状是堆空间错误:

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)
    ...

当我切换到一个更大的实例并调高mapred.child.java.opts设置时,我得到了一个新的错误:

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

Hadoop的snappy编解码器无法处理外部生成的文件。

对于选项(2),问题是hadoop流不区分换行符和换行符。由于快速压缩最终会在压缩文件中散布这些字节码,这是致命的。这是我的错误跟踪:

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问题。但正如我最初所说,我的目标是在hadoop流媒体模块中构建,而不涉及Java。有了这个限制,似乎没有任何方法可以解决这个问题。

最后,我回到了生成这个集群正在使用的文件的人那里,并说服他们切换到gzip或lzo。

PS-在选项(2)中,我尝试了在不同的字符上拆分记录(例如textinputformat.record.delimiter=X),但它感觉非常粗糙,无论如何都不起作用。

PPS-另一种解决方法是编写脚本从S3下载文件,解压缩它们,然后运行copyFromLocal将它们拉入HDFS。从计算上来说,这没有错,但从工作流的角度来看,这会带来各种麻烦。

 类似资料:
  • 我们使用Apache Camel来压缩和解压缩我们的文件。我们使用标准的和API。 我们的问题是,当我们得到非常大的文件(例如800MB到1GB以上的文件大小)时,我们的应用程序将耗尽内存,因为整个文件被加载到内存中进行压缩和解压缩。 是否有任何骆驼API或java库可以帮助压缩/解压缩文件,而不需要将整个文件加载到内存中。 这里还有一个类似的未解问题

  • 我正在使用Julia的ZipFile包来提取和处理csv文件。没问题,但是当我遇到zip文件中的zip文件时,我也想处理它,但是遇到了一个错误。 Julia ZipFile文档如下:https://zipfilejl.readthedocs.io/en/latest/ 对如何做到这一点有什么想法吗?

  • 问题内容: 我想使用urllib下载文件,并在保存之前对文件进行解压缩。 这就是我现在所拥有的: 最终将写入空文件。我该如何实现自己的追求? 更新的答案: 问题答案: 在写完之后,但要传递给之前,您需要寻找到开始的地方。否则它将被模块从头读取,并显示为空文件。见下文:

  • 问题内容: 是否可以压缩日志文件(我通过RollingFileAppender进行压缩)? 问题答案: log4j Extras 支持该功能。只需在配置中添加以下内容,文件名以 .gz 结尾即可自动压缩日志文件: 有关更多详细信息,请查看Javadoc

  • 问题内容: 我想使用Web浏览器在客户端显示OpenOffice文件,.odt和.odp。 这些文件是压缩文件。使用Ajax,我可以从服务器获取这些文件,但是它们是压缩文件。我必须使用JavaScript解压缩它们,我尝试使用inflate.js,http: //www.onicos.com/staff/iz/amuse/javascript/expert/inflate.txt ,但没有成功。