Hadoop 压缩

压缩

压缩是指将数据转换为比原来的格式占用空间更小的格式来存储,以达到减小存储空间
解压是压缩的反过程

Hadoop文件切片

Hadoop MapReduce是通过划分切片来处理得,这样就使得支持分割的压缩格式更适合Hadoop

针对ss.txt文件大小为300M

  • 计算公式
    computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M(Hadoop 1.x中块大小为64M)
  • 默认情况下,切片大小=blocksize
  • 开始切,形成第1个切片:ss.txt—0:128M 第2个切片ss.txt—128:256M 第3个切片ss.txt—256M:300M(每次切片时,都要判断切完剩下的部分是否大于块的1.1倍,不大于1.1倍就划分一块切片)

注意:
切片主要由这几个值来运算决定

1
2
mapreduce.input.fileinputformat.split.minsize=1 默认值为1
mapreduce.input.fileinputformat.split.maxsize= Long.MAXValue 默认Long.MAXValue

因此,默认情况下,切片大小=blocksize。

  • maxsize(切片最大值):参数如果调得比blocksize小,则会让切片变小,而且就等于配置的这个参数的值。
  • minsize(切片最小值):参数调的比blockSize大,则可以让切片变得比blocksize还大。

Hadoop压缩

Hadoop作为一个叫通用的海量数据处理平台,在压缩方面主要考虑压缩速度和压缩的可分割性


小提示: 使用gzip压缩文件时

  • -9表示空间优先,也就是先考虑压缩空间的减小
  • -1表示时间优先,也就是压缩速度要快

Hadoop支持的压缩格式

压缩格式 工具 算法 扩展名 多文件 可分割性 换成压缩格式后,原来的程序是否需要修改
DEFLATE DEFLATE .deflate 和文本处理一样,不需要修改
GZIP gzip DEFLATE .gzp 和文本处理一样,不需要修改
ZIP zip DEFLATE .zip 是,在文件范围内
BZIP2 bzip2 BZIP2 .bz2 和文本处理一样,不需要修改
LZO lzop LZO .lzo 需要建索引,还需要指定输入格式

压缩算法及其编码/解码器

压缩格式 对应的编码/解码器
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
http://google.github.io/snappy/
On a single core of a Core i7 processor in 64-bit mode, Snappy compresses at about 250 MB/sec or more and decompresses at about 500 MB/sec or more.

压缩格式选择

Gzip压缩

  • 优点:压缩率比较高,而且压缩/解压速度也比较快;hadoop本身支持,在应用中处理gzip格式的文件就和直接处理文本一样;大部分linux系统都自带gzip命令,使用方便。
  • 缺点:不支持split。

    应用场景:当每个文件压缩之后在130M以内的(1个块大小内),都可以考虑用gzip压缩格式。例如说一天或者一个小时的日志压缩成一个gzip文件,运行mapreduce程序的时候通过多个gzip文件达到并发。hive程序,streaming程序,和java写的mapreduce程序完全和文本处理一样,压缩之后原来的程序不需要做任何修改。

Bzip2压缩

  • 优点:支持split;具有很高的压缩率,比gzip压缩率都高;hadoop本身支持,但不支持native(java和c互操作的API接口);在linux系统下自带bzip2命令,使用方便。
  • 缺点:压缩/解压速度慢;不支持native。

    应用场景:适合对速度要求不高,但需要较高的压缩率的时候,可以作为mapreduce作业的输出格式;或者输出之后的数据比较大,处理之后的数据需要压缩存档减少磁盘空间并且以后数据用得比较少的情况;或者对单个很大的文本文件想压缩减少存储空间,同时又需要支持split,而且兼容之前的应用程序(即应用程序不需要修改)的情况。

Lzo压缩

  • 优点:压缩/解压速度也比较快,合理的压缩率;支持split,是hadoop中最流行的压缩格式;可以在linux系统下安装lzop命令,使用方便。
  • 缺点:压缩率比gzip要低一些;hadoop本身不支持,需要安装;在应用中对lzo格式的文件需要做一些特殊处理(为了支持split需要建索引,还需要指定inputformat为lzo格式)。

    应用场景:一个很大的文本文件,压缩之后还大于200M以上的可以考虑,而且单个文件越大,lzo优点越越明显。

    Snappy压缩

  • 优点:高速压缩速度和合理的压缩率。
  • 缺点:不支持split;压缩率比gzip要低;hadoop本身不支持,需要安装;

    应用场景:当Mapreduce作业的Map输出的数据比较大的时候,作为Map到Reduce的中间数据的压缩格式;或者作为一个Mapreduce作业的输出和另外一个Mapreduce作业的输入。

Hadoop 压缩案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public class Demo {
public static void main(String[] args) throws IOException, ClassNotFoundException {

//压缩为bz2格式
compress("org.apache.hadoop.io.compress.BZip2Codec");
}

private static void compress(String method) throws ClassNotFoundException, IOException {

//1. 获取resources下的资源文件流
InputStream in = Demo.class.getClassLoader().getResourceAsStream("properties.xml");

//2. 通过Java反射机制创建对应得编码名称
Class<?> codeClass = Class.forName(method);

//3. 通过编码名称找对应得编码/解码器
Configuration conf = new Configuration();

CompressionCodec codec = (CompressionCodec) ReflectionUtils.newInstance(codeClass, conf);

//4. 指定压缩后的文件,codec.getDefaultExtension()获得相应的扩展名
File fileOut = new File(System.currentTimeMillis() + codec.getDefaultExtension());
//如果文件存在,删除,否则什么也不做
fileOut.delete();

//5. 创建输出流
FileOutputStream out = new FileOutputStream(fileOut);

//6. 通过编码/解码器创建对应得输出流
CompressionOutputStream cout = codec.createOutputStream(out);

//7. 压缩输出
/**
* in 输入流
* cout 压缩输出流
* 1024 缓冲大小
* false 不关闭相应流,true则关闭
*/
IOUtils.copyBytes(in,cout,4096,false);
in.close();
cout.close();
}
/**
* 解压缩
* @param file
* @throws IOException
*/
private static void decompress(File file) throws IOException {
Configuration conf = new Configuration();
CompressionCodecFactory factory = new CompressionCodecFactory(conf);

//通过扩展名获得编码/解码器
CompressionCodec codec = factory.getCodec(new Path(file.getName()));

//通过编码解码器获得输入流
CompressionInputStream in = codec.createInputStream(new FileInputStream(file));

IOUtils.copyBytes(in, System.out, 4096, true);
}

}

说明:snappy压缩格式在Windows运行失败,不过打包放到集群里面是可以的,前提是你的hadoop集群支持snappy压缩格式

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×