HDFS支持數據壓縮的幾種方法探討

HDFS支持數據壓縮存在以下幾種方法:

1、在HDFS之上將數據壓縮好後,再存儲到HDFS
2、在HDFS內部支持數據壓縮,這裏又可以分爲幾種方法:
    2.1、壓縮工作在DataNode上完成,這裏又分兩種方法:
           2.1.1、數據接收完後,再壓縮
                     這個方法對HDFS的改動最小,但效果最低,只需要在block文件close後,調用壓縮工具,將block文件壓縮一下,然後再打開block文件時解壓一下即可,幾行代碼就可以搞定
           2.1.2、邊接收數據邊壓縮,使用第三方提供的壓縮庫
                     效率和複雜度折中方法,Hook住系統的write和read操作,在數據寫入磁盤之前,先壓縮一下,但write和read對外的接口行爲不變,比如:原始大小爲100KB的數據,壓縮後大小爲10KB,當寫入100KB後,仍對調用者返回100KB,而不是10KB
    2.2、壓縮工作交給DFSClient做,DataNode只接收和存儲
           這個方法效果最高,壓縮分散地推給了HDFS客戶端,但DataNode需要知道什麼時候一個block塊接收完成了。

推薦最終實現採用2.2這個方法,該方法需要修改的HDFS代碼量也不大,但效果最高。


這裏舉一個例子:
 先說文件的壓縮有兩大好處:1、可以減少存儲文件所需要的磁盤空間;2、可以加速數據在網絡和磁盤上的傳輸。尤其是在處理大數據時,這兩大好處是相當重要的。

  下面是一個使用gzip工具壓縮文件的例子。將文件/user/hadoop/aa.txt進行壓縮,壓縮後爲/user/hadoop/text.gz

  1. package com.hdfs;

  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.io.OutputStream;
  5. import java.net.URI;

  6. import org.apache.hadoop.conf.Configuration;
  7. import org.apache.hadoop.fs.FSDataInputStream;
  8. import org.apache.hadoop.fs.FSDataOutputStream;
  9. import org.apache.hadoop.fs.FileSystem;
  10. import org.apache.hadoop.fs.Path;
  11. import org.apache.hadoop.io.IOUtils;
  12. import org.apache.hadoop.io.compress.CompressionCodec;
  13. import org.apache.hadoop.io.compress.CompressionCodecFactory;
  14. import org.apache.hadoop.io.compress.CompressionInputStream;
  15. import org.apache.hadoop.io.compress.CompressionOutputStream;
  16. import org.apache.hadoop.util.ReflectionUtils;

  17. public class CodecTest {
  18.     //壓縮文件
  19.     public static void compress(String codecClassName) throws Exception{
  20.         Class<?> codecClass = Class.forName(codecClassName);
  21.         Configuration conf = new Configuration();
  22.         FileSystem fs = FileSystem.get(conf);
  23.         CompressionCodec codec = (CompressionCodec)ReflectionUtils.newInstance(codecClass, conf);
  24.         //指定壓縮文件路徑
  25.         FSDataOutputStream outputStream = fs.create(new Path("/user/hadoop/text.gz"));
  26.         //指定要被壓縮的文件路徑
  27.         FSDataInputStream in = fs.open(new Path("/user/hadoop/aa.txt"));
  28.         //創建壓縮輸出流
  29.         CompressionOutputStream out = codec.createOutputStream(outputStream);  
  30.         IOUtils.copyBytes(in, out, conf);
  31.         IOUtils.closeStream(in);
  32.         IOUtils.closeStream(out);
  33.     }
  34.    
  35.     //解壓縮
  36.     public static void uncompress(String fileName) throws Exception{
  37.         Class<?> codecClass = Class.forName("org.apache.hadoop.io.compress.GzipCodec");
  38.         Configuration conf = new Configuration();
  39.         FileSystem fs = FileSystem.get(conf);
  40.         CompressionCodec codec = (CompressionCodec)ReflectionUtils.newInstance(codecClass, conf);
  41.         FSDataInputStream inputStream = fs.open(new Path("/user/hadoop/text.gz"));
  42.          //把text文件裏到數據解壓,然後輸出到控制檯  
  43.         InputStream in = codec.createInputStream(inputStream);  
  44.         IOUtils.copyBytes(in, System.out, conf);
  45.         IOUtils.closeStream(in);
  46.     }
  47.    
  48.     //使用文件擴展名來推斷二來的codec來對文件進行解壓縮
  49.     public static void uncompress1(String uri) throws IOException{
  50.         Configuration conf = new Configuration();
  51.         FileSystem fs = FileSystem.get(URI.create(uri), conf);
  52.         
  53.         Path inputPath = new Path(uri);
  54.         CompressionCodecFactory factory = new CompressionCodecFactory(conf);
  55.         CompressionCodec codec = factory.getCodec(inputPath);
  56.         if(codec == null){
  57.             System.out.println("no codec found for " + uri);
  58.             System.exit(1);
  59.         }
  60.         String outputUri = CompressionCodecFactory.removeSuffix(uri, codec.getDefaultExtension());
  61.         InputStream in = null;
  62.         OutputStream out = null;
  63.         try {
  64.             in = codec.createInputStream(fs.open(inputPath));
  65.             out = fs.create(new Path(outputUri));
  66.             IOUtils.copyBytes(in, out, conf);
  67.         } finally{
  68.             IOUtils.closeStream(out);
  69.             IOUtils.closeStream(in);
  70.         }
  71.     }
  72.    
  73.     public static void main(String[] args) throws Exception {
  74.         //compress("org.apache.hadoop.io.compress.GzipCodec");
  75.         //uncompress("text");
  76.         uncompress1("hdfs://master:9000/user/hadoop/text.gz");
  77.     }

  78. }
複製代碼
首先執行77行進行壓縮,壓縮後執行第78行進行解壓縮,這裏解壓到標準輸出,所以執行78行會再控制檯看到文件/user/hadoop/aa.txt的內容。如果執行79行的話會將文件解壓到/user/hadoop/text,他是根據/user/hadoop/text.gz的擴展名判斷使用哪個解壓工具進行解壓的。解壓後的路徑就是去掉擴展名。

  進行文件壓縮後,在執行命令./hadoop fs -ls /user/hadoop/查看文件信息,如下:
  1. [hadoop@master bin]$ ./hadoop fs -ls /user/hadoop/
  2. Found 7 items
  3. -rw-r--r--   3 hadoop supergroup   76805248 2013-06-17 23:55 /user/hadoop/aa.mp4
  4. -rw-r--r--   3 hadoop supergroup        520 2013-06-17 22:29 /user/hadoop/aa.txt
  5. drwxr-xr-x   - hadoop supergroup          0 2013-06-16 17:19 /user/hadoop/input
  6. drwxr-xr-x   - hadoop supergroup          0 2013-06-16 19:32 /user/hadoop/output
  7. drwxr-xr-x   - hadoop supergroup          0 2013-06-18 17:08 /user/hadoop/test
  8. drwxr-xr-x   - hadoop supergroup          0 2013-06-18 19:45 /user/hadoop/test1
  9. -rw-r--r--   3 hadoop supergroup         46 2013-06-19 20:09 /user/hadoop/text.gz

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章