在我的MR工作中,让我们说,我指定地图的压缩或减少输出到LZO,它是如何压缩的?来自map或reduce任务的整个数据是否首先在没有压缩的情况下获得,然后在最后,未压缩的数据被压缩,或者是否逐步压缩和写入。如果它被逐步压缩和写入,那么它是如何完成的?请帮我理解这一点。
谢谢,
Venkat
答案 0 :(得分:3)
它主要取决于您使用的文件类型。如果是文本文件,则在文件级别进行压缩。但如果它是SequenceFile,则压缩可以是记录级别或块级别。请注意,这里的块表示使用序列文件而不是hdfs块的缓冲区。
如果是块压缩,则会立即将多个记录压缩到块中。记录将添加到块中,直到达到最小字节数。通过从缓冲区大小中减去压缩算法的最大开销来计算一次要压缩的输入数据的最大大小。默认缓冲区大小为512字节,对于压缩开销,zlib算法为18字节(bufferSize的1%+ 12字节)。然后使用给定的输出流和压缩器创建BlockCompressorStream,并写入压缩数据。
希望这在某种程度上回答了这个问题。
答案 1 :(得分:3)
我想我会通过解释压缩在更高级别的mapreduce管道中的位置来为Tariq的答案添加更多细节。希望它有用。
如果为地图阶段(mapreduce.map.output.compress=true
)指定压缩,则将使用您指定的任何编解码器(mapreduce.map.ouput.compress.codec=org.apache.hadoop.io.compress.*
)压缩中间地图输出数据,并在每张地图结束时保存到磁盘任务完成(如果映射任务超出序列化缓冲区限制,则更早,并开始溢出到磁盘)。然后,在Shuffle& amp; amp; amp; amp;和/或对mapreduce作业进行排序。
在这个阶段(地图输出),压缩结果在拆分方面没有任何好处,因此GZIP或Snappy编解码器在这里以及LZO和BZIP2都值得尝试。 GZIP通常对大多数数据具有更好的压缩比,但是大量消耗CPU,而Snappy在压缩比较低的情况下速度更快(即它具有更少的延迟或者不像GZIP那样消耗CPU ......我对此并不积极原因)。使用teragen生成的数据,GZIP与Snappy的压缩比分别为3.5倍和2.5倍。显然,您的数据和硬件限制将决定您最有利的编解码器是什么。
shuffle& amp;之前的压缩排序阶段有助于减少磁盘IO,并减少网络带宽,因为您通过网络发送压缩数据。我想不出在这个阶段不压缩数据的好理由,只要没有争用这样做的CPU资源。在我的小10节点上,在1 Gb网络上运行的Hadoop集群仅针对地图输出阶段打开压缩(即,在混洗和排序阶段被压缩之前的中间地图数据;最终输出未被压缩)改善了整个作业时间 41%(GZIP), 45%(Snappy)与不使用压缩的100GB terasort作业。这些实验中的数据是使用teragen生成的。当然,您的结果会因数据集,硬件和网络而异。
然后在缩减阶段开始时压缩压缩数据。
压缩在最终输出的reduce阶段结束时再次发挥作用(mapreduce.output.fileoutputformat.compress = true)。如果您将输出提供给另一个mapreduce作业,则可以使用可拆分LZO或BZIP2压缩。如果您不在输出上使用可拆分压缩编解码器并对该数据运行作业,则只能使用一个映射器,这会破坏Hadoop的主要优点之一;并行化。解决这个问题并使用类似GZIP编解码器的方法之一是为输出创建一个序列文件。序列文件是可拆分的,因为它本质上是一系列附加在一起的压缩文件。序列文件可以在每个文件附加到另一个文件的边界处拆分。