bBHadoop数据压缩

概述

运行hadoop程序时,I/O操作、网络数据传输、shuffle和merge要花大量的时间,尤其是数据规模很大和工作负载密集的情况下,这个时候,使用数据压缩可以提高效率

压缩策略和原则

压缩是提高Hadoop运行效率的一种策略

通过对Mapper、Reducer运行过程的数据进行压缩,减少磁盘IO,提高运行速度

压缩原则

  1. 运算密集型的job,少用压缩

  2. IO密集型的job,多用压缩

总结:当面对一些较大IO量的数据是,使用压缩会提高效率

Hadoop支持的压缩编码

压缩格式 hadoop自带? 算法 文件扩展名 是否可切片 换成压缩格式后,原来的程序是否需要修改
DEFLATE 是,直接使用 DEFLATE .deflate 否 和文本处理一样,不需要修改
Gzip 是,直接使用 DEFLATE .gz 否 和文本处理一样,不需要修改
bzip2 是,直接使用 bzip2 .bz2 是 和文本处理一样,不需要修改
LZO 否,需要安装 LZO .lzo 是 需要建索引,还需要指定输入格式
Snappy 是,直接使用 Snappy .snappy 否 和文本处理一样,不需要修改

为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器,如下表所示。

压缩格式 对应的编码/解码器
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

压缩方式的选择

GZIP压缩

优点:压缩率较高,压缩解压速度快,hadoop和linux自带,方便
缺点:不支持切片
应用场景:因为GZIP压缩不支持切片,所以当每个文件压缩之后再130M以内,都可以考虑使用GZIP压缩格式,例如吧一天的日志压缩成GZIP

BigZIP2压缩

优点:支持Split;具有很高的压缩率,比Gzip压缩率都要,Hadoop自带,方便
缺点:速度慢
应用场景:适合对速度要求不高,但需要较高压缩率的时候。或者对单个很大的文本文件想压缩减少存储空间,同时又需要支持Split,而且兼容之间的应用程序的时候

LZO压缩

优点:解压缩速度快,合理的压缩率。支持Split(需要建立索引),是Hadoop中最流行的压缩格式;可以在Linux下安装LZO命令,
缺点:压缩率比Gzip要低一些;Hadoop本身不支持,需要安装;在应用中对LZO格式的文件要做一些特殊处理(为了支持Split要建索引,并且把InputFormat指定为LZO格式)
应用场景:一个很大的文件,压缩之后还大于200M以上的可以考虑,而且单个文件越大,Lzo优点越明显

Snaapy压缩

优点:高速压缩速度和合理的压缩率
缺点:不支持Split;压缩率比Gzip还要低;Hadoop本身不支持,需要安装
应用场景:当MR作业中Map输出的数据较大时,作为Map到Reduce的中间数据的压缩格式;或者作为一个MR的输出到另外一个MR的输入
MR流程图内,map-shuffle落盘之间适合使用此压缩算法

压缩位置的选择

压缩可以在MR作用的任意阶段启用

  • 在输入端启用压缩

    有大量数据并计划重复处理的情况下,应该考虑对数据进行压缩;
    这时候无序指定压缩编码,Hadoop能自动检测文件拓展名,如果拓展名能够匹配,就会匹配恰当的编码方式对文件进行压缩和解压,否则就不会进行压缩/解压
  • 在Mapper输出启用压缩

    当Map任务输出的中间数据量很大时,应在此阶段考虑此压缩技术,能显著提升Shuffle效率
    shuffle过程在Hadoop处理过程中资源消耗最多的环节,如果发现数据量大造成网络传输缓慢,应考虑使用压缩技术,可用于Mapper输出的快速编码器包括LZO和Snappy

注意事项(建议Mapper输出阶段使用LZO压缩编码,会让Map阶段完成时间快4倍)

LZO是供Hadoop压缩数据用的通用编码器,其设计目标是达到与硬盘读取速度相当的压缩速度,因此速度是LZO优先考虑的因素,而不是压缩率
与Gzip编解码器相比,它的压缩速度是Gzip的5倍,而解压速度是Gzip的2倍。同一个文件用LZO压缩后比用Gzip压缩后大50%,但比压缩前小25%~50%。这对改善性能非常有利,Map阶段完成时间快4倍。
  • Reduce端

    在此阶段使用压缩可以降低磁盘使用量,在进行链条式作业时也同样有效

压缩参数配置

要在Hadoop中启用压缩,可以配置如下参数:

参数 默认值 阶段 建议
io.compression.codecs (在core-site.xml中配置) 无,这个需要在命令行输入hadoop checknative查看 输入压缩 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
mapreduce.output.fileoutputformat.compress.type(在mapred-site.xml中配置) RECORD reducer输出 SequenceFile输出使用的压缩类型:NONE和BLOCK

数据压缩案例

CompressionCodec有两个方法可以用于轻松地压缩或解压缩数据。

要想对正在被写入一个输出流的数据进行压缩,我们可以使用createOutputStream(OutputStreamout)方法创建一个CompressionOutputStream,将其以压缩格式写入底层的流

相反,要想对从输入流读取而来的数据进行解压缩,则调用createInputStream(InputStreamin)函数,从而获得一个CompressionInputStream,从而从底层的流读取未压缩的数据。

压缩数据据案例

测试一下如下压缩方式:
DEFLATE org.apache.hadoop.io.compress.DefaultCodec
gzip org.apache.hadoop.io.compress.GzipCodec
bzip2 org.apache.hadoop.io.compress.BZip2Codec
​
package com.atguigu.mapreduce.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.CompressionInputStream;
import org.apache.hadoop.io.compress.CompressionOutputStream;
​
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
​
public class TestCompress {
   public static void main(String[] args) throws IOException {
       compress("D:\\input\\inputcompression\\JaneEyre.txt"
,"org.apache.hadoop.io.compress.BZip2Codec");
       //decompress("D:\\input\\inputcompression\\JaneEyre.txt.bz2");
  }
   //压缩
   private static void compress(String filename, String method) throws IOException {
       //1 获取输入流
       FileInputStream fis = new FileInputStream(new File(filename));
​
       //2 获取输出流
       //获取压缩编解码器codec
       CompressionCodecFactory factory = new CompressionCodecFactory(new Configuration());
       CompressionCodec codec = factory.getCodecByName(method);
​
       //获取普通输出流,文件后面需要加上压缩后缀
       FileOutputStream fos = new FileOutputStream(new File(filename + codec.getDefaultExtension()));
       //获取压缩输出流,用压缩解码器对fos进行压缩
       CompressionOutputStream cos = codec.createOutputStream(fos);
​
       //3 流的对拷
       IOUtils.copyBytes(fis,cos,new Configuration());
​
       //4 关闭资源
       IOUtils.closeStream(cos);
       IOUtils.closeStream(fos);
       IOUtils.closeStream(fis);
  }
//解压缩
   private static void decompress(String filename) throws IOException {
       //0 校验是否能解压缩
       CompressionCodecFactory factory = new CompressionCodecFactory(new Configuration());
       CompressionCodec codec = factory.getCodec(new Path(filename));
       if (codec == null) {
           System.out.println("cannot find codec for file " + filename);
           return;
      }
       //1 获取输入流
       FileInputStream fis = new FileInputStream(new File(filename));
       CompressionInputStream cis = codec.createInputStream(fis);
​
       //2 获取输出流
       FileOutputStream fos = new FileOutputStream(new File(filename + ".decodec"));
​
       //3 流的对拷
       IOUtils.copyBytes(cis,fos,new Configuration());
​
       //4 关闭资源
       IOUtils.closeStream(fos);
       IOUtils.closeStream(cis);
       IOUtils.closeStream(fis);
  }
}

Map输出端采用压缩

即使MR任务的输出输出文件都是未压缩格式的文件,也可以在Map和Reduce传输阶段使用压缩,因为它要写在磁盘并通过网络传输,用压缩可以提高很多性能而这些工作只要设置两个属性即可

import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.compress.BZip2Codec;
import org.apache.hadoop.io.compress.CompressionCodec;
import org.apache.hadoop.io.compress.GzipCodec;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
​
public class WordCountDriver {
​
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
​
Configuration conf = new Configuration();
​
// 开启map端输出压缩
conf.setBoolean("mapreduce.map.output.compress", true);
// 设置map端输出压缩方式
conf.setClass("mapreduce.map.output.compress.codec", BZip2Codec.class,CompressionCodec.class);
​
Job job = Job.getInstance(conf);
​
job.setJarByClass(WordCountDriver.class);
​
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
​
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
​
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
​
FileInputFormat.setInputPaths(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
​
boolean result = job.waitForCompletion(true);
​
System.exit(result ? 0 : 1);
}
}

Reduce输出端采用压缩

Reduce输出端需要设置驱动,两行代码搞定

​
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.compress.BZip2Codec;
import org.apache.hadoop.io.compress.DefaultCodec;
import org.apache.hadoop.io.compress.GzipCodec;
import org.apache.hadoop.io.compress.Lz4Codec;
import org.apache.hadoop.io.compress.SnappyCodec;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
​
public class WordCountDriver {
​
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {

Configuration conf = new Configuration();

Job job = Job.getInstance(conf);

job.setJarByClass(WordCountDriver.class);

job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);

job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);

job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);

FileInputFormat.setInputPaths(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));

// 设置reduce端输出压缩开启
FileOutputFormat.setCompressOutput(job, true);
// 设置压缩的方式
   FileOutputFormat.setOutputCompressorClass(job, BZip2Codec.class);
//   FileOutputFormat.setOutputCompressorClass(job, GzipCodec.class);
//   FileOutputFormat.setOutputCompressorClass(job, DefaultCodec.class);
   
boolean result = job.waitForCompletion(true);

System.exit(result?0:1);
}
}

Hadoop优化之数据压缩的更多相关文章

  1. SQL Server-聚焦存储过程性能优化、数据压缩和页压缩提高IO性能(一)

    前言 关于SQL Server基础系列尚未结束,还剩下最后一点内容未写,后面会继续.有园友询问我什么时候开始写SQL Server性能系列,估计还得等一段时间,最近工作也比较忙,但是会陆陆续续的更新S ...

  2. 关注云端搜索技术:elasticsearch,nutch,hadoop,nosql,mongodb,hbase,cassandra 及Hadoop优化

    http://www.searchtech.pro/ Hadoop添加或调整的参数: 一.hadoop-env.sh1.hadoop的heapsize的设置,默认1000 # The maximum ...

  3. HADOOP与HDFS数据压缩格式

    1.cloudera 数据压缩的一般准则 一般准则 是否压缩数据以及使用何种压缩格式对性能具有重要的影响.在数据压缩上,需要考虑的最重要的两个方面是 MapReduce 作业和存储在 HBase 中的 ...

  4. 学习笔记:Twitter核心数据类库团队的Hadoop优化经验

    一.来源 Streaming Hadoop Performance Optimization at Scale, Lessons Learned at Twitter (Data platform @ ...

  5. Hadoop优化

    一.影响MR程序效率的因素 1.计算机性能: CPU.内存.磁盘.网络, 计算机的性能会影响MR程序的速度与效率 2.I/O方面 1)数据倾斜(代码优化) 2)map和reduce数量设置不合理(通过 ...

  6. Hadoop优化 第一篇 : HDFS/MapReduce

    比较惭愧,博客很久(半年)没更新了.最近也自己搭了个博客,wordpress玩的还不是很熟,感兴趣的朋友可以多多交流哈!地址是:http://www.leocook.org/ 另外,我建了个QQ群:3 ...

  7. hadoop优化之拙见

    map-reduce的优化: 需要内存的地方:  map/reduce任务运行时内存.存放中间数据的内存缓存区.map输出数据排序内存, 需要操作磁盘的地方: map输出数据缓冲区达到阀值的溢出写文件 ...

  8. Hadoop(24)-Hadoop优化

    1. MapReduce 跑得慢的原因 优化方法 MapReduce优化方法主要从六个方面考虑:数据输入.Map阶段.Reduce阶段.IO传输.数据倾斜问题和常用的调优参数. 数据输入 Map阶段 ...

  9. Hadoop优化 操作系统优化

    1.优化文件系统,修改/etc/fstab 在defaults后面添加noatime,表示不记录文件的访问时间. 修改为: 如果不想重新启动操作系统使配置生效,那么应该执行: # mount -o r ...

随机推荐

  1. 从零造就JVM大牛(一)

    引言 从事java的小伙伴大家好,如果你是一名从事java行业的程序员,无论你是小白还是工作多年的老司机,我相信这篇文章一定会给你带来 不同程度的收货不敢说你看完我的文章从此精通jvm打遍天下无对手, ...

  2. B. Kay and Snowflake 解析(思維、DFS、DP、重心)

    Codeforce 685 B. Kay and Snowflake 解析(思維.DFS.DP.重心) 今天我們來看看CF685B 題目連結 題目 給你一棵樹,要求你求出每棵子樹的重心. 前言 完全不 ...

  3. ABP 数据访问 - IRepository 仓储

    ABP系列,这个系列来的比较晚,很多大佬其实已经分析过,为什么现在我又来一轮呢? 1.想自己来完整的学习一轮ABP 2.公司目前正在使用ABP,准备迁移Core 基于以上的目的,开始这个系列 ABP ...

  4. plc模拟量采集模块的作用

    在工业控制中,某些输入量(如压力.温度.流量.转速等)是连续变化的模拟量,某些执行机构(如伺服电动机.调节阀.记录仪等)要求PLC输出模拟信号,而PLC的CPU只能处理数字量.模拟量首先被传感器和变送 ...

  5. 1.DRF初始化

    1.DRF框架的8个核心功能   1.认证(用户登录校验用户名密码或者token是否合法) 2.权限(根据不同的用户角色,可以操作不同的表) 3.限流(限制接口访问速度) 4.序列化(返回json) ...

  6. WeihanLi.Npoi 1.11.0/1.12.0 Release Notes

    WeihanLi.Npoi 1.11.0/1.12.0 Release Notes Intro 最近 NPOI 扩展新更新了两个版本,感谢 shaka chow 的帮忙和支持,这两个 Feature ...

  7. c++ templates 第二版(英文)

    关注公众号:红宸笑. 回复:电子书 即可

  8. 美团笔试题_ACM最多队伍

    题目: 选择队伍参加ACM比赛,可以选择的人由N+M组成,N代表N个擅长算法的人,M代表M个擅长编程的人,选择要求:每个队伍三个人,每个队伍中至少有一个擅长算法的人,至少有一个擅长编程的人.求可以组成 ...

  9. youtube-dl 源码看看,例子是下载网页

    1, 跑起来 下载 youtube-dl, 配合 launch.json, # 本文中 himala 是代指,具体见文末的 github repo "configurations" ...

  10. Python--安装 PyQt5, pyqt5-tools

    # 使用豆瓣镜像源 anaconda prompt界面里输入: pip install pyqt5-tools -i https://pypi.douban.com/simple/