打怪升级之小白的大数据之旅(五十七)
Hadoop压缩
上次回顾
介绍完zookeeper之后,接下来就是Hadoop的扩展知识点,压缩和HA了,因为HA是建立在zookeeper基础上的,所以我现在才带来这个知识点
Hadoop压缩
压缩概述
- 首先我们要知道,压缩是一种对数据的优化方法
- 使用压缩可以有效减少HDFS存储数据的读写字节数,提高网络带宽和磁盘空间的使用效率
- 因为运行MR操作时,Shuffle和Merge要花费大量的时间,所以使用压缩可以提高我们MR程序的工作效率
压缩的优缺点
- 虽然通过对MR过程中的数据进行压缩可以减少磁盘IO来提高MR程序运行速度,但压缩同时增加了CPU的运算负担
- 因为压缩后的数据需要解压缩才可以使用,所以压缩特效运用得当可以提高性能,运用不当也可能降低性能
使用压缩的场景
了解了压缩的优缺点,我们自然就可以猜到压缩的应用场景了吧?
- 运算密集型的任务(job),我们尽量少用压缩
- IO密集型的任务(job),我们要多用压缩
MR的压缩编码
- 压缩也分为很多种格式,因为它们的底层算法不同
- 通过不同的压缩技术,我们可以针对不同的场景来使用压缩
- 下面,让我们来了解一下MR支持的几种压缩技术
MR支持的压缩编码
压缩格式 | hadoop自带? | 算法 | 文件扩展名 | 是否可切分 | 换成压缩格式后,原来的程序是否需要修改 |
DEFLATE | 是,直接使用 | DEFLATE | .deflate | 否 | 和文本处理一样,不需要修改 |
Gzip | 是,直接使用 | DEFLATE | .gz | 否 | 和文本处理一样,不需要修改 |
bzip2 | 是,直接使用 | bzip2 | .bz2 | 是 | 和文本处理一样,不需要修改 |
LZO | 否,需要安装 | LZO | .lzo | 是 | 需要建索引,还需要指定输入格式 |
Snappy | 否,需要安装 | Snappy | .snappy | 否 | 和文本处理一样,不需要修改 |
Hadoop的编码/解码API
压缩格式 | 对应的编码/解码器 |
DEFLATE | org.apache.hadoop.io.compress.DefaultCodec |
gzip | org.apache.hadoop.io.compress.GzipCodec |
bzip2 | org.apache.hadoop.io.compress.BZip2Codec |
LZO | com.hadoop.compression.lzo.LzopCodec |
Snappy | org.apache.hadoop.io.compress.SnappyCodec |
压缩性能比较
压缩算法 | 原始文件大小 | 压缩文件大小 | 压缩速度 | 解压速度 |
gzip | 8.3GB | 1.8GB | 17.5MB/s | 58MB/s |
bzip2 | 8.3GB | 1.1GB | 2.4MB/s | 9.5MB/s |
LZO | 8.3GB | 2.9GB | 49.3MB/s | 74.6MB/s |
snappy | 8.3GB | 4GB | 250MB/s | 500MB/s |
snappy的压缩速度是最快的,但是它的压缩效果是最低的,基本上只能将文件压缩至源文件的一半大小左右,想要了解snappy的小伙伴可以参考github的说明:http://google.github.io/snappy
压缩参数配置
参数 | 默认值 | 阶段 | 建议 |
io.compression.codecs (在core-site.xml中配置 |
| 输入压缩 | Hadoop使用文件扩展名判断是否支持某种编解码器 |
mapreduce.map.output.compress(在mapred-site.xml中配置) | false | mapper输出 | 这个参数设为true启用压缩 |
mapreduce.map.output.compress.codec(在mapred-site.xml中配置) | org.apache.hadoop.io.compress.DefaultCodec | mapper输出 | 企业多使用LZO或Snappy编解码器在此阶段压缩数据 |
mapreduce.output.fileoutputformat.compress(在mapred-site.xml中配置) | false | reducer输出 | 这个参数设为true启用压缩 |
mapreduce.output.fileoutputformat.compress.codec(在mapred-site.xml中配置) | org.apache.hadoop.io.compress.DefaultCodec | reducer输出 | 使用标准工具或者编解码器,如gzip和bzip2 |
表格是为了让大家方便查看,下面来总结一下压缩应用场景
- Gzip
- Hadoop本身支持,使用方便,因为在程序中处理Gzip格式的文件就和直接处理文本一样,并且大部分的linux系统都有Gzip命令
- 因为Gzip不支持切片,所以当单个文件压缩的大小约等于一个块以内(130M左右),我们可以采用Gzip
- Bzip2
- Bzip2同样是Hadoop自带的一种压缩格式,它的特点是支持对单个很大的文本文件压缩时又想对其进行切片,此时我们就选择使用Bzip
- 但是Bzip2的压缩、解压缩的速度比较慢
- Lzo
- 压缩、解压缩速度块,支持切片,是我们最常使用的压缩格式之一,我们可以在Linux中安装lzop命令来使用它
- Lzo在使用的时候需要对Lzo格式文件做一些特殊处理,比如为了支持切片,我们需要建立索引,并且指定InputFormat为Lzo格式
- Lzo的特点是压缩后数据量大小还大于200M的时候使用
- Lzo最大的优势就是单个文件越大,它的压缩效率优势就越明显
- Snappy
- 它的特点就一个字,快,高速的压缩、解压缩效率,让其他压缩望尘莫及
- 但是它不支持切片并且压缩后的大小是源文件的一半
- 正因为它很快,所以我们通常在MR的Map阶段数据比较大的时候作为Map到Reduce的中间格式,或者作为一个MR作业输出到另一个MR作业输入的时候使用
数据流的压缩和解压缩
- 了解了压缩和解压缩以及MR支持的格式之后,下面我们通过代码来演示具体压缩是怎么创建使用的
- 在Hadoop中,我们可以使用内置的CompressionCodec对象来创建压缩流完成对文件的压缩、解压缩
package com.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.*;
import org.apache.hadoop.util.ReflectionUtils;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class CompressDemo {
/**
* 压缩
*/
@Test
public void test() throws Exception {
//1.输入流--普通文件流
FileInputStream fis = new FileInputStream("D:\\io\\compress\\aaa.txt");
//2.输出流--压缩流
//2.1创建对应的编解码器的对象
CompressionCodec gzipCodec =
ReflectionUtils.newInstance(GzipCodec.class, new Configuration());
//2.2创建流
//gzipCodec.getDefaultExtension() : 获取压缩类型的扩展名
CompressionOutputStream cos = gzipCodec.createOutputStream(
new FileOutputStream("D:\\io\\decompress\\aaa.txt" +
gzipCodec.getDefaultExtension()));
//3.文件对拷
IOUtils.copyBytes(fis,cos,1024,true);
}
/**
* 解压缩
*/
@Test
public void test2() throws Exception {
//输入流---压缩流
CompressionCodec gzipCodec =
ReflectionUtils.newInstance(GzipCodec.class, new Configuration());
CompressionInputStream cis = gzipCodec.createInputStream(
new FileInputStream("D:\\io\\decompress\\aaa.txt.gz"));
//输出流---普通的文件流
FileOutputStream fos = new FileOutputStream("D:\\io\\compress\\aaa.txt");
//3.文件对拷
IOUtils.copyBytes(cis,fos,1024,true);
}
/**
* 解压缩
*/
@Test
public void test3() throws Exception {
//创建压缩的工厂类
CompressionCodecFactory factory = new CompressionCodecFactory(new Configuration());
//输入流---压缩流
//根据文件的扩展名创建对应的编解码器类的对象(智能)
CompressionCodec gzipCodec =
factory.getCodec(new Path("D:\\io\\decompress\\aaa.txt.gz"));
if (gzipCodec != null){//没有对应的编解码器的对象
CompressionInputStream cis = gzipCodec.createInputStream(
new FileInputStream("D:\\io\\decompress\\aaa.txt.gz"));
//输出流---普通的文件流
FileOutputStream fos = new FileOutputStream("D:\\io\\compress\\aaa.txt");
//3.文件对拷
IOUtils.copyBytes(cis,fos,1024,true);
}
}
}
总结
本章对压缩的知识点进行分享,了解并使用压缩是在我们日常工作中必不可少的知识之一,合理的使用压缩可以大大提高我们程序的执行效率,好了,本章内容就是这些,下一章为大家带来Hadoop的HA