压缩是一种通过特定的算法来减小计算机文件大小的机制。这种机制是一种很方便的发明,尤其是对网络用户,因为它可以减小文件的字节总数,使文件能够通过较慢的互联网连接实现更快传输,此外还可以减少文件的磁盘占用空间。
——摘自百度百科
简而言之,通过一定的算法对数据进行特殊编码,使得数据存储的空间更小,此过程称为压缩,反之为解压缩,与Windows和Mac或者手机的压缩类似。
0x01 Hadoop压缩机制a. 无论使用哪种压缩工具,都需要权衡时间和空间,要么时间长空间少,要么时间短空间大
b. 在大数据领域,特别需要考虑压缩文件的可分割性,它会影响到在执行作业时Map启动的个数,从而会影响到作业的执行效率!
c. Hadoop会自动识别压缩格式。如果压缩的文件有相应压缩格式的扩展名(比如lzo
,gz
,bzip2
等)。Hadoop会自动选择相对应的解码器来解压数据,我们只需要确保输入的压缩文件有扩展名即可。
a. Hadoop支持的编码/解码器如下表
压缩格式 | 工具 | 算法 | 扩展名 | 多文件 | 可分割性 |
---|---|---|---|---|---|
DEFLATE | 无 | DEFLATE | .deflate | 不 | 不 |
GZIP | gzip | DEFLATE | .gzp | 不 | 不 |
ZIP | zip | DEFLATE | .zip | 是 | 是,在文件范围内 |
BZIP2 | bzip2 | BZIP2 | .bz2 | 不 | 是 |
LZO | lzop | LZO | .lzo | 不 | 是 |
b. 常见的有:DEFLATE(默认)、gzip、bzip以及Snappy
c. 性能比较(摘自ABM):
压缩算法 | 原始文件大小 | 压缩文件大小 | 压缩速度 | 解压速度 |
---|---|---|---|---|
gzip | 8.3GB | 1.8GB | 17.5MB/s | 58MB/s |
bzip2 | 8.3GB | 1.1GB | 2.4MB/s | 9.5MB/s |
LZO-bset | 8.3GB | 2GB | 4MB/s | 60.6MB/s |
LZO | 8.3GB | 2.9GB | 49.3MB/s | 74.6MB/s |
因此我们可以得出:
所有的压缩算法都显示出一种时间空间的权衡,更快的压缩和解压速度通常会耗费更多的空间。在选择使用哪种压缩格式时,我们应该根据自身的业务需求来选择。
下图是在本地压缩与通过流将压缩结果上传到BI的时间对比:
a. 通过反射的方式,对应的类如下
gzip => org.apache.hadoop.io.compress.GzipCodec bzip => org.apache.hadoop.io.compress.BZipCodec snappy => org.apache.hadoop.io.compress.SnappyCodec DEFLATE => org.apache.hadoop.io.compress.DefaultCodec
b. 在选择压缩方式时,替换掉相应的类即可。
a. 完整代码
package com.shaonaiyi.hadoop.filetype.compress; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IOUtils; import org.apache.hadoop.io.compress.CompressionCodec; import org.apache.hadoop.io.compress.CompressionCodecFactory; import org.apache.hadoop.io.compress.CompressionOutputStream; import org.apache.hadoop.util.ReflectionUtils; import java.io.*; /** * @Author shaonaiyi@163.com * @Date 2019/12/17 10:28 * @Description Hadoop压缩机制 */ public class CompressTest { public static void main(String[] args) throws IOException, ClassNotFoundException { //压缩 compress("blockByte.txt", "org.apache.hadoop.io.compress.GzipCodec"); //解压 // decompress(new File("blockByte.txt.gz")); } private static File compress(String fileName, String compressClassName) throws ClassNotFoundException, IOException { Class<?> codecClass = Class.forName(compressClassName); Configuration configuration = new Configuration(); CompressionCodec codec = (CompressionCodec) ReflectionUtils.newInstance(codecClass, configuration); File fileOut = new File(fileName + codec.getDefaultExtension()); fileOut.delete(); OutputStream out = new FileOutputStream(fileOut); CompressionOutputStream cout = codec.createOutputStream(out); File fileIn = new File(fileName); InputStream in = new FileInputStream(fileIn); IOUtils.copyBytes(in, cout, 4096, false); in.close(); cout.close(); return fileOut; } private static void decompress(File file) throws IOException { Configuration configuration = new Configuration(); CompressionCodecFactory factory = new CompressionCodecFactory(configuration); CompressionCodec codec = factory.getCodec(new Path(file.getName())); if (codec == null) { System.out.println("找不到文件->" + file); return; } File fileOut = new File(file.getName() + "-dec.txt"); InputStream in = codec.createInputStream(new FileInputStream(file)); OutputStream outputStream = new FileOutputStream(fileOut); IOUtils.copyBytes(in, outputStream, 4096, false); in.close(); outputStream.close(); } }
b. 压缩后,发现项目路径下多了一个blockByte.txt.gz
文件
c. 解压后,发现项目路径下多了一个blockByte.txt.gz-dec.txt
文件
GzipCodec
。FileOutputFormat.setCompressOutput(job, true); FileOutputFormat.setOutputCompressorClass(job, GzipCodec.class);
3. 参考文章:Hadoop 压缩实现分析
作者简介:邵奈一
全栈工程师、市场洞察者、专栏编辑
| 公众号 | 微信 | 微博 | CSDN | 简书 |
福利:
邵奈一的技术博客导航
邵奈一 原创不易,如转载请标明出处。