【Hadoop篇08】Hadoop数据压缩

    技术2022-07-11  93

    简洁而不简单

    Hadoop数据压缩

    数据压缩优点和缺点

    ​ 压缩技术能够有效减少底层存储系统(HDFS)读写字节数。压缩提高了网络带宽和磁盘空间的效率。在 Hadoop下,尤其是数据规模很大和工作负载密集的情况下,使用数据压缩显得非常重要。在这种情况下,IO操作和网络数据传输要花大量的时间。还有, Shuffle与 Merge过程同样也面临着巨大的IO压力鳘于磁盘IO和网络带宽是 Hadoop的宝贵资源,数据压缩对于节省资源、最小化磁盘IO和网络传输非常有帮助。

    ​ 不过,尽管压缩与解压操作的CPU开销不髙,其性能的提升和资源的节省并非没有代价。如果磁盘IO和网络带宽影响了 MapReduce作业性能,在任意 MapReduce阶段启用压缩都可以改善端到端处理时间并減少IO和网络流量。

    压缩策略和原则

    ​ 压缩是提高 Hadoop运行效率的一种优化策略通过对 Mapper、 Reducer运行过程的数据进行压缩,以减少磁盘IO,提高MR程序运行速度。 ​ 注意:釆用压缩技术减少了磁盘IO,但同时增加了CPU运算负担。所以,压缩特性运用得当能提高性能,但运用不当也可能降低性能压缩基本原则:

    (1)运算密集型的job,少用压缩 (2)IO密集型的job,多用压缩!!

    MR支持的压缩编码

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

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

    压缩格式对应的编码/解码器DEFLATEorg.apache.hadoop.io.compress.DefaultCodecgziporg.apache.hadoop.io.compress.GzipCodecbzip2org.apache.hadoop.io.compress.BZip2CodecLZOcom.hadoop.compression.lzo.LzopCodecSnappyorg.apache.hadoop.io.compress.SnappyCodec

    压缩性能的比较

    压缩算法原始文件大小压缩文件大小压缩速度解压速度gzip8.3GB1.8GB17.5MB/s58MB/sbzip28.3GB1.1GB2.4MB/s9.5MB/sLZO8.3GB2.9GB49.3MB/s74.6MB/s

    压缩方式选择

    Gzip压缩

    Bzip2压缩

    Lzo压缩

    Snappy压缩

    压缩位置选择

    压缩参数配置

    参数默认值阶段建议io.compression.codecs (在core-site.xml中配置)org.apache.hadoop.io.compress.DefaultCodec, org.apache.hadoop.io.compress.GzipCodec, org.apache.hadoop.io.compress.BZip2Codec输入压缩Hadoop使用文件扩展名判断是否支持某种编解码器mapreduce.map.output.compress(在mapred-site.xml中配置)falsemapper输出这个参数设为true启用压缩mapreduce.map.output.compress.codec(在mapred-site.xml中配置)org.apache.hadoop.io.compress.DefaultCodecmapper输出使用LZO或Snappy编解码器在此阶段压缩数据mapreduce.output.fileoutputformat.compress(在mapred-site.xml中配置)falsereducer输出这个参数设为true启用压缩mapreduce.output.fileoutputformat.compress.codec(在mapred-site.xml中配置)org.apache.hadoop.io.compress. DefaultCodecreducer输出使用标准工具或者编解码器,如gzip和bzip2mapreduce.output.fileoutputformat.compress.type(在mapred-site.xml中配置)RECORDreducer输出SequenceFile输出使用的压缩类型:NONE和BLOCK

    压缩案例

    public class TestCompress { public static void main(String[] args) throws Exception { compress("e:/hello.txt","org.apache.hadoop.io.compress.BZip2Codec"); // decompress("e:/hello.txt.bz2"); } // 1、压缩 private static void compress(String filename, String method) throws Exception { // (1)获取输入流 FileInputStream fis = new FileInputStream(new File(filename)); Class codecClass = Class.forName(method); CompressionCodec codec = (CompressionCodec) ReflectionUtils.newInstance(codecClass, new Configuration()); // (2)获取输出流 FileOutputStream fos = new FileOutputStream(new File(filename +codec.getDefaultExtension())); CompressionOutputStream cos = codec.createOutputStream(fos); // (3)流的对拷 IOUtils.copyBytes(fis, cos, 1024*1024*5, false); // (4)关闭资源 fis.close(); cos.close(); fos.close(); } // 2、解压缩 private static void decompress(String filename) throws FileNotFoundException, 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)获取输入流 CompressionInputStream cis = codec.createInputStream(new FileInputStream(new File(filename))); // (2)获取输出流 FileOutputStream fos = new FileOutputStream(new File(filename + ".decoded")); // (3)流的对拷 IOUtils.copyBytes(cis, fos, 1024*1024*5, false); // (4)关闭资源 cis.close(); fos.close(); } }

    Map输出端采用压缩

    public class WordCountDriver { public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException { Configuration configuration = new Configuration(); // 开启map端输出压缩 configuration.setBoolean("mapreduce.map.output.compress", true); // 设置map端输出压缩方式 configuration.setClass("mapreduce.map.output.compress.codec", BZip2Codec.class, CompressionCodec.class); Job job = Job.getInstance(configuration); 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 ? 1 : 0); } }

    Mapper和Reducer代码不变

    Reduce输出端采用压缩

    public class WordCountDriver { public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException { Configuration configuration = new Configuration(); Job job = Job.getInstance(configuration); 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?1:0); } }

    相关资料

    本文配套GitHub:https://github.com/zhutiansama/FocusBigData

    Processed: 0.012, SQL: 9