【问题标题】:Load snappy-compressed files into Elastic MapReduce将 snappy 压缩文件加载到 Elastic MapReduce
【发布时间】:2013-03-21 21:17:38
【问题描述】:

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

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

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

【问题讨论】:

    标签: hadoop amazon-web-services compression hadoop-streaming emr


    【解决方案1】:

    答案是“做不到”。至少,不适用于将 hadoop 流应用到源自 hadoop 之外的 snappy 压缩文件的特定情况。

    我(彻底!)探索了两个主要选项来得出这个结论:(1)尝试使用 hadoop 的内置 snappy 压缩,如 highcaffeinated 建议的那样,或(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 流不区分 \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 类的一些工作(例如,参见 here),我们或许可以解决 \r 与 \n 的问题。但正如我最初所说,我的目标是在 hadoop 流模块中构建,而不涉及 Java。有了这个限制,似乎没有办法解决这个问题。

    最后,我回到生成该集群正在消耗的文件的人那里,并说服他们切换到 gzip 或 lzo。

    PS - 在选项 (2) 上,我尝试在不同的字符上拆分记录(例如 textinputformat.record.delimiter=X),但感觉很笨拙,无论如何都没有用。

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

    【讨论】:

      【解决方案2】:

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

      您可能需要考虑使用 lzo 压缩(.gz 扩展名)而不是 snappy。您放弃一些压缩速度以获得更好的压缩率和可拆分的输入文件。 Cloudera 提到了这个in their blog

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

      【讨论】:

      • 我听到你对 LZO 与 snappy 的比较,对于其他未来做类似事情的人,我也推荐 LZO。就我而言,管理存储到 S3 的团队还有其他原因更喜欢 snappy,而且它不会严重影响我们在 hadoop 中的性能。所以我们坚持使用快速压缩。
      • 另外,您提到的基于文件扩展的神奇检测不适用于许多 hadoop 版本。我正在使用 AWS EMR AMI 2.3.3,版本 1.0.3,但它在那里不起作用。我也尝试了其他几个 EMR 版本,但没有任何乐趣。
      猜你喜欢
      • 1970-01-01
      • 2017-02-02
      • 1970-01-01
      • 1970-01-01
      • 2021-01-28
      • 1970-01-01
      • 1970-01-01
      • 2015-04-20
      • 1970-01-01
      相关资源
      最近更新 更多