Hadoop输入的最佳可分割压缩格式是bz2吗?

29
我们意识到太晚了,将我们的文件以GZip格式进行Hadoop处理的归档并不是一个好主意。 GZip无法分割,以下是问题的参考资料,我不再赘述: 我的问题是:BZip2是否是最佳归档压缩,使单个归档文件可以由Hadoop并行处理? Gzip明显不是,从我阅读的内容来看,LZO也存在一些问题。

Snappy是Spark用于Parquet文件的默认压缩算法,也是另一个很好的选择。 - Powers
4个回答

32
BZIP2 在Hadoop中是可以分割的,它提供了非常好的压缩比,但从CPU时间和性能方面来看,效果并不理想,因为压缩非常耗费CPU资源。 LZO 在Hadoop中是可以分割的,借助于 hadoop-lzo,您可以拥有可分割的压缩 LZO 文件。你需要一个外部的 .lzo.index 文件才能并行处理。该库提供了在本地或分布式方式下生成这些索引的所有手段。 LZ4 在Hadoop中是可以分割的,借助于 hadoop-4mc,您可以拥有可分割的压缩 4mc 文件。您不需要任何外部索引,并且您可以使用提供的命令行工具或Java/C代码在Hadoop内/外生成存档。4mc 可以在 Hadoop 中提供任何速度/压缩比级别的 LZ4:从快速模式达到 500 MB/s 的压缩速度,到提供增加的压缩比的高/超级模式,几乎与 GZIP 相当。

4
最近我更喜欢使用LZ4。 - Pradeep Gollakota
1
你竟然没有包含Zlib,让我感到惊讶。 - nikk
@nikk zstd的最初版本发布于2015年,该帖子可以追溯到2014年。 - Sarye Haddadi

6
这里有五种使用gzip的方法,其中三种需要索引,两种不需要。
可以为任何gzip文件创建索引,即不需要特殊构造,如zran.c所做。然后,您可以从块边界开始解压缩。索引包括每个入口点处32K的未压缩数据历史记录。
如果您正在构建gzip文件,则可以使用周期性入口点进行制作,其索引不需要那些入口点处的未压缩历史记录,从而使索引更小。这是在zlib中使用Z_FULL_FLUSH选项对deflate()进行的。
您还可以在每个这样的点上执行Z_SYNC_FLUSH,然后执行Z_FULL_FLUSH,这将插入两个标记。然后,您可以搜索九个字节的模式00 00 ff ff 00 00 00 ff ff以找到它们。这与在bzip2文件中搜索六个字节的标记没有区别,只是用九个字节时虚假阳性的可能性要小得多。然后您就不需要单独的索引文件了。

gzip和xz都支持简单的串联。 这使您可以轻松地准备归档以进行另一种并行解压缩。 简而言之:

gzip < a > a.gz
gzip < b > b.gz
cat a.gz b.gz > c.gz
gunzip < c.gz > c
cat a b | cmp - c

这将导致比较成功。

然后,您可以根据所需大小分块压缩并连接结果。保存每个gzip流的偏移量的索引。从这些偏移量解压缩。您可以根据应用程序选择块的大小。但是,如果它们太小,压缩将受到影响。

通过简单地连接gzip文件,如果使每个块具有固定的未压缩大小,则还可以放弃索引。然后,每个块以相同的四个字节结尾,即按little-endian顺序的未压缩长度,例如对于1 MiB块,为00 00 10 00,后跟来自下一块的1f 8b 08,它是gzip标头的开头。该七字节标记可以像bzip2标记一样进行搜索,尽管存在更小的误报概率。

对于连接的xz文件,同样可以使用七个字节的标头:fd 37 7a 58 5a 00 00


谢谢!如何准备gzip/bzip2文件并使它们具有可分割的入口点? - Suman
提示:由于我没有找到 hadoop fs -bzcat 命令,可以使用以下命令代替:hadoop fs -cat /FILENAME.bz | bzcat | less - xgMz
根据 http://comphadoop.weebly.com/ 的说法,bzip2 是可分割的,但 gzip 不行。 - samthebest
4
我认为这并没有真正回答问题。在Hadoop世界中,“可分割”是一个非常具体的概念,而GZIP并不可分割。 - davideanastasia
@davideanastasia:如果你想的话,gzip是可以分割的。请查看更新后的答案。 - Mark Adler

6
我不认为其他答案是正确的。根据这个网站:http://comphadoop.weebly.com/,bzip2是可分割的。如果索引了LZO也是可分割的。所以答案是肯定的,如果你想使用比文件更多的映射器,那么你需要使用bzip2。
为了做到这一点,您可以编写一个简单的MR作业来读取数据,然后将其再次写出,然后您需要确保设置mapred.output.compression.codecorg.apache.hadoop.io.compress.BZip2Codec

1
我会选择这个答案,但是如果您也能告诉我们“如何”做,那就更好了:我该如何创建索引化的bz2文件? - Gavriel
@Gavriel 我不知道如何创建索引LZO,但我会更新我的答案,简要解释如何压缩到bzip2。 - samthebest
我使用gzip压缩来输出,因为RedShift可以读取这种格式。但是,任何正确的bzip2文件都可以作为输入吗?还是我需要传递一些特殊参数来获取块/索引? - Gavriel
你不需要使用bzip2进行索引,只需要使用LZO即可。大多数大数据工具会通过查看文件扩展名自动处理各种压缩格式。 - samthebest

1

我的建议是,bzip 写入速度非常慢。在 Apache Spark 1.6.2、Hadoop 2.7 上测试了一个简单的 JSON 文件压缩,大小为 50GB,使用 bzip 比 gzip 花费的时间多 2 倍。

但是使用 bzip 可以将 50GB 压缩成 4GB!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接