Hadoop作为一个较通用的海量数据处理平台,每次运算都会需要处理大量数据,我们会在 Hadoop系统中对数据进行压缩处理来优化磁盘使用率,提高数据在磁盘和网络中的传输速度,从而提高系统处理数据的效率。在使用压缩方式方面,主要考虑压缩速度和压缩文件的可分割性。综合所述,使用压缩的优点如下:
1.节省数据占用的磁盘空间;
2.加快数据在磁盘和网络中的传输速度,从而提高系统的处理速度。
压缩格式
Hadoop对于压缩格式的是自动识别。如果我们压缩的文件有相应压缩格式的扩展名(如 lzo,gz,bzip2等)。Hadoop会根据压缩格式的扩展名自动选择相对应的解码器来解压数据,此过程由Hadoop自动处理,我们只需要确保输入的压缩文件有扩展名。
Hadoop对每个压缩格式的支持, 详细见下表:
表 1. 压缩格式
压缩格式 | 工具 | 算法 | 扩展名 | 多文件 | 可分割性 |
---|---|---|---|---|---|
DEFLATE | 无 | DEFLATE | .deflate | 不 | 不 |
GZIP | gzip | DEFLATE | .gzp | 不 | 不 |
ZIP | zip | DEFLATE | .zip | 是 | 是,在文件范围内 |
BZIP2 | bzip2 | BZIP2 | .bz2 | 不 | 是 |
LZO | lzop | LZO | .lzo | 不 | 是 |
性能对比
Hadoop下各种压缩算法的压缩比,压缩时间,解压时间见下表:
表 2. 性能对比
压缩算法 | 原始文件大小 | 压缩文件大小 | 压缩速度 | 解压速度 |
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 |
因此我们可以得出:
1) Bzip2压缩效果明显是最好的,但是 bzip2压缩速度慢,可分割。
2) Gzip压缩效果不如 Bzip2,但是压缩解压速度快,不支持分割。
3) LZO压缩效果不如 Bzip2 和 Gzip,但是压缩解压速度最快!并且支持分割!
文件的可分割性在 Hadoop中是很非常重要的,它会影响到在执行作业时 Map启动的个数,从而会影响到作业的执行效率!
所有的压缩算法都显示出一种时间空间的权衡,更快的压缩和解压速度通常会耗费更多的空间。在选择使用哪种压缩格式时,我们应该根据自身的业务需求来选择。
使用方式
MapReduce可以在三个阶段中使用压缩。
1.输入压缩文件。如果输入的文件是压缩过的,那么在被 MapReduce读取时,它们会被自动解压。
2.MapReduce作业中,对 Map 输出的中间结果集压缩。实现方式如下:
conf.setBoolean("mapreduce.compress.map.output", true);
conf.setClass("mapreduce.map.output.compression.codec", GzipCodec.class, CompressionCodec.class);
最后一行代码指定 Map输出结果的编码器。
3.MapReduce作业中,对 Reduce 输出的最终结果集压。实现方式如下:
FileOutputFormat.setCompressOutput(job, true);
FileOutputFormat.setOutputCompressorClass(job, GzipCodec.class);
压缩解压工厂类 CompressionCodecFactory
压缩解压工厂类 CompressionCodeFactory.class 主要功能就是负责根据不同的文件扩展名来自动获取相对应的压缩解压器 CompressionCodec.class,是整个压缩框架的核心控制器。接下来用代码来说明压缩和解压缩:
压缩文件:
FSDataInputStream data_in = fs.open(pathlist[0]); //打开文件 获取文件输入流
byte[] buf = new byte[1000];
int len = data_in.read(buf); //读取文件数据至buf中
Class<?> codecClass = GzipCodec.class;
CompressionCodec codec = (CompressionCodec) codecClass.newInstance();
FSDataOutputStream zip_out = fs.create(new Path(Pathoutput)); //创建zip文件的输出路径
CompressionOutputStream pre_out = codec.createOutputStream(zip_out);
pre_out.write(buf, 0, len); //将数据buf写入zip文件中
pre_out.finish();
FSDataInputStream data_in = fs.open(pathlist[0]); //打开文件 获取文件输入流
byte[] buf = new byte[1000];
int len = data_in.read(buf); //读取文件数据至buf中
Class<?> codecClass = GzipCodec.class;
CompressionCodec codec = (CompressionCodec) codecClass.newInstance();
FSDataOutputStream zip_out = fs.create(new Path(Pathoutput)); //创建zip文件的输出路径
CompressionOutputStream pre_out = codec.createOutputStream(zip_out);
pre_out.write(buf, 0, len); //将数据buf写入zip文件中
pre_out.finish();
解压文件:
CompressionCodecFactory factory = new CompressionCodecFactory(conf);
Path path = new Path(Pathinput);
CompressionCodec codec = factory.getCodec(path);
FSDataInputStream data_in = fs.open(new Path(Pathinput));
CompressionInputStream pre_in = codec.createInputStream(data_in);
byte[] buf = new byte[1000];
int len = pre_in.read(buf, 0, buf.length);
System.out.println(len);
pre_in.close();
String str = new String(buf, 0, len);
System.out.println(str);
//将读取到的zip文件中的数据写入到txt中
FSDataOutputStream data_out = fs.create(new Path(Pathoutput));
data_out.write(buf, 0, len);
data_out.close();
结束语
通过对 Hadoop平台压缩框架的学习,对各压缩格式的效率进行对比分析,能够在使用Hadoop平台时,通过对数据进行压缩处理来提高数据处理效率。当再次面临海量数据处理时,Hadoop平台的压缩机制可以让我们事半功倍。