Hadoop壓縮的圖文教程

近期因爲Hadoop集羣機器硬盤資源緊張,有需求讓把 Hadoop 集羣上的歷史數據進行下壓縮,開始從網上查找的都是關於各類壓縮機制的對比,不多有關於怎麼壓縮的教程(我沒找到。。),再此特記錄下本次壓縮的過程,方便之後查閱,利己利人。java

 

本文涉及的全部 jar包、腳本、native lib 見文末的相關下載 ~git

 

個人壓縮版本: github

Jdk 1.7及以上算法

Hadoop-2.2.0 版本bash

 

壓縮前環境準備:分佈式

關於壓縮算法對比,網上資料不少,這裏我用的是 Bzip2 的壓縮方式,比較中庸,因爲是Hadoop自帶的壓縮機制,也不須要額外下載別的東西,只須要在 Hadoop根目錄下 lib/native 文件下有以下文件便可:oop

 

 

 

 

壓縮以前要檢查 Hadoop 集羣支持的壓縮算法: hadoop checknative大數據

每臺機器都要檢查一下,都顯示如圖 true 則說明 集羣支持 bzip2 壓縮,優化

若是顯示false 則須要將上圖的文件下載拷貝到 Hadoop根目錄下 lib/native編碼

 

 

 

壓縮程序介紹:

 

壓縮程序用到的類 getFileList(獲取文件路徑) 、 FileHdfsCompress(壓縮類)、FileHdfsDeCompress(解壓縮類) ,只用到這三個類便可完成壓縮/解壓縮操做。

 

 

 

 

getFileList 做用:遞歸打印 傳入文件目錄下文件的根路徑,包括子目錄下的文件。開始想直接輸出到文件中,後來打包放到集羣上運行時,發現文件沒有內容,多是因爲分佈式運行的關係,因此就把路徑打印出來,人工在放到文件中。

 

核心代碼:
public static void listAllFiles(String path, List<String> strings) throws IOException {
        FileSystem hdfs = getHdfs(path);
        Path[] filesAndDirs = getFilesAndDirs(path);

        for(Path p : filesAndDirs){
            if(hdfs.getFileStatus(p).isFile()){
                if(!p.getName().contains("SUCCESS")){
                    System.out.println(p);
                }
            }else{
                listAllFiles(p.toString(),strings);
            }
        }
       // FileUtils.writeLines(new File(FILE_LIST_OUTPUT_PATH), strings,true);

    }

public static FileSystem getHdfs(String path) throws IOException {
        Configuration conf = new Configuration();
        return FileSystem.get(URI.create(path),conf);
    }


public static Path[] getFilesAndDirs(String path) throws IOException { FileStatus[] fs = getHdfs(path).listStatus(new Path(path)); return FileUtil.stat2Paths(fs); }

  

 FileHdfsCompress:壓縮程序很是簡單,對應程序裏的 FileHdfsCompress 類,(解壓縮是 FileHdfsDeCompress),採用的是Hadoop 原生API  ,將Hadoop集羣上原文件讀入做爲輸入流,將壓縮路徑的輸入流做爲輸出,再使用相關的壓縮算法即,代碼以下:

 

核心代碼:

 //指定壓縮方式
            Class<?> codecClass = Class.forName(COMPRESS_CLASS_NAME);

            Configuration conf = new Configuration();
            CompressionCodec codec = (CompressionCodec)ReflectionUtils.newInstance(codecClass, conf);
            // FileSystem fs = FileSystem.get(conf);
            FileSystem fs = FileSystem.get(URI.create(inputPath),conf);

            //原文件路徑 txt 用本來的輸入流讀入
            FSDataInputStream in = fs.open(new Path(inputPath));

            //建立 HDFS 上的輸出流,壓縮路徑
            //經過文件系統獲取輸出流
            OutputStream out = fs.create(new Path(FILE_OUTPUT_PATH));
            //對輸出流的數據壓縮
            CompressionOutputStream compressOut = codec.createOutputStream(out);
            //讀入原文件 壓縮到HDFS上 輸入--普通流  輸出-壓縮流
            IOUtils.copyBytes(in, compressOut, 4096,true);

  

如下是代碼優化的過程,不涉及壓縮程序使用,不感興趣同窗能夠跳過 ~ :

 

在實際編碼中,我實際上是走了彎路的,一開始並無想到用 Hadoop API 就能實現壓縮解壓縮功能,代碼到此實際上是經歷了優化迭代的過程。

 

最開始時壓縮的思路就是 將文件讀進來,再壓縮出去,一開始使用了 MapReduce 的方式,在編碼過程當中,因爲對生成壓縮文件的路徑還有要求,又在 Hadoop 輸出時自定義了輸出類來使的輸出文件的名字符合要求,不是 part-r-0000.txt ,而是時間戳.txt 的格式,至此符合原線上路徑的要求。

 

而在實際運行過程當中發現,MR 程序須要啓動 Yarn,並佔用Yarn 資源,因爲壓縮時間較長,有可能會長時間佔用 集羣資源不釋放,後來發現 MR 程序的初衷是用來作並行計算的,而壓縮僅僅是 map 任務讀取一條就寫一條,不涉及計算,就是內容的簡單搬運。因此這裏放棄了使用 MR 想着可不能夠就用簡單的 Hadoop API 就完成壓縮功能,通過一番嘗試後,發現真的可行! 使用了 Hadoop API 釋放了集羣資源,壓縮速度也還能夠,這樣就把這個壓縮程序當作一個後臺進程跑就好了也不用考慮集羣資源分配的問題

 

實測壓縮步驟:

 

1 將項目打包,上傳到hadoop 集羣任一節點便可,準備好相應的腳本,輸入數據文件,日誌文件,以下圖:

 

 

 

 

2 使用獲取文件路徑腳本,打印路徑: 

 

 

 

getFileLish.sh 腳本內容以下,就是簡單調用,傳入參數爲 hadoop集羣上 HDFS 上目錄路徑

#!/bin/sh

echo "begin get fileList"

echo "第一個參數$1"

if [ ! -n "$1" ]; then
echo "check param!"
fi

#original file
hadoop jar hadoop-compress-1.0.jar com.people.util.getFileList  $1

  

3 將 打印的路徑 粘貼到 compress.txt 中,第 2 步中會把目錄的文件路徑包括子目錄路徑都打印出來,將其粘貼進  compress.txt 中便可,注意 文件名可隨意定

 

4 使用壓縮腳本便可,sh compress.sh /data/new_compress/compress.txt  ,加粗的部分是腳本的參數意思是 第3步中文件的路徑,注意:這裏只能是絕對路徑,否則可能報找不到文件的異常。

 

 

 compress.sh 腳本內容以下,就是簡單調用,傳入參數爲 第3步中文件的絕對路徑

 

#!/bin/sh
echo "begin compress"

echo "第一個參數$1"

if [ ! -n "$1" ]; then
echo "check param!"
fi


hadoop jar hadoop-compress-1.0.jar com.people.compress.FileHdfsCompress  $1 >> /data/new_compress/compress.log 2>&1 &

  

 

5 查看壓縮日誌,發現後臺程序已經開始壓縮了!,tail  -f  compress.log

 

6 若是感受壓縮速度不夠,能夠多臺機器執行腳本,也能夠一臺機器執行多個任務,由於這個腳本任務是一個後臺進程,不會佔用集羣 Yarn 資源。

 

 相關下載:

 

程序源碼下載: git@github.com:fanpengyi/hadoop-compress.git

 

Hadoop 壓縮相關須要的 腳本、jar包、lib 下載: 關注公衆號 「大數據江湖」,後臺回覆 「hadoop壓縮」,便可下載

 

長按便可關注

 

 --- The End ---

相關文章
相關標籤/搜索