HDFS支援資料壓縮的幾種方法探討
阿新 • • 發佈:2019-02-19
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塊接收完成了。
進行檔案壓縮後,在執行命令./hadoop fs -ls /user/hadoop/檢視檔案資訊,如下:
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
- package com.hdfs;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.net.URI;
- import org.apache.hadoop.conf.Configuration;
- import org.apache.hadoop.fs.FSDataInputStream;
- import org.apache.hadoop.fs.FSDataOutputStream;
- import org.apache.hadoop.fs.FileSystem;
- 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 org.apache.hadoop.util.ReflectionUtils;
- public class CodecTest {
- //壓縮檔案
- public static void compress(String codecClassName) throws Exception{
- Class<?> codecClass = Class.forName(codecClassName);
- Configuration conf = new Configuration();
- FileSystem fs = FileSystem.get(conf);
- CompressionCodec codec = (CompressionCodec)ReflectionUtils.newInstance(codecClass, conf);
- //指定壓縮檔案路徑
- FSDataOutputStream outputStream = fs.create(new Path("/user/hadoop/text.gz"));
- //指定要被壓縮的檔案路徑
- FSDataInputStream in = fs.open(new Path("/user/hadoop/aa.txt"));
- //建立壓縮輸出流
- CompressionOutputStream out = codec.createOutputStream(outputStream);
- IOUtils.copyBytes(in, out, conf);
- IOUtils.closeStream(in);
- IOUtils.closeStream(out);
- }
- //解壓縮
- public static void uncompress(String fileName) throws Exception{
- Class<?> codecClass = Class.forName("org.apache.hadoop.io.compress.GzipCodec");
- Configuration conf = new Configuration();
- FileSystem fs = FileSystem.get(conf);
- CompressionCodec codec = (CompressionCodec)ReflectionUtils.newInstance(codecClass, conf);
- FSDataInputStream inputStream = fs.open(new Path("/user/hadoop/text.gz"));
- //把text檔案裡到資料解壓,然後輸出到控制檯
- InputStream in = codec.createInputStream(inputStream);
- IOUtils.copyBytes(in, System.out, conf);
- IOUtils.closeStream(in);
- }
- //使用副檔名來推斷二來的codec來對檔案進行解壓縮
- public static void uncompress1(String uri) throws IOException{
- Configuration conf = new Configuration();
- FileSystem fs = FileSystem.get(URI.create(uri), conf);
- Path inputPath = new Path(uri);
- CompressionCodecFactory factory = new CompressionCodecFactory(conf);
- CompressionCodec codec = factory.getCodec(inputPath);
- if(codec == null){
- System.out.println("no codec found for " + uri);
- System.exit(1);
- }
- String outputUri = CompressionCodecFactory.removeSuffix(uri, codec.getDefaultExtension());
- InputStream in = null;
- OutputStream out = null;
- try {
- in = codec.createInputStream(fs.open(inputPath));
- out = fs.create(new Path(outputUri));
- IOUtils.copyBytes(in, out, conf);
- } finally{
- IOUtils.closeStream(out);
- IOUtils.closeStream(in);
- }
- }
- public static void main(String[] args) throws Exception {
- //compress("org.apache.hadoop.io.compress.GzipCodec");
- //uncompress("text");
- uncompress1("hdfs://master:9000/user/hadoop/text.gz");
- }
- }
進行檔案壓縮後,在執行命令./hadoop fs -ls /user/hadoop/檢視檔案資訊,如下:
- [hadoop@master bin]$ ./hadoop fs -ls /user/hadoop/
- Found 7 items
- -rw-r--r-- 3 hadoop supergroup 76805248 2013-06-17 23:55 /user/hadoop/aa.mp4
- -rw-r--r-- 3 hadoop supergroup 520 2013-06-17 22:29 /user/hadoop/aa.txt
- drwxr-xr-x - hadoop supergroup 0 2013-06-16 17:19 /user/hadoop/input
- drwxr-xr-x - hadoop supergroup 0 2013-06-16 19:32 /user/hadoop/output
- drwxr-xr-x - hadoop supergroup 0 2013-06-18 17:08 /user/hadoop/test
- drwxr-xr-x - hadoop supergroup 0 2013-06-18 19:45 /user/hadoop/test1
- -rw-r--r-- 3 hadoop supergroup 46 2013-06-19 20:09 /user/hadoop/text.gz