Hadoop集群合并小文件

Hadoop集群本身不推荐存储小文件,因为在mapreduce程序调度过程中,默认map的输入是不跨文件的,如果一个文件很小(远小于一个块的大小,目前集群块大小是256M),在调度时也会生成一个map,且一个map只处理这个小文件,这样mapreduce程序执行,其实大部分时间都消耗在调度过程中,而不是执行mapreduce程序过程中,这样会使得程序的执行效率很低。

         所以在Hadoop集群上应该尽量保障存储的文件尽量大,这样在文件put到集群上时,会将文件按块大小切块,在执行mapreduce过程中,又会将块切分成片,然后将一个切片作为一个map输入,一个map处理的将是一个块大小(一个map的输入最大也就是一个块大小),这样mapreduce程序的执行时间都可以认为是map程序和reduce程序的执行时间,而调度的时间可以忽略不计,这样整个集群的执行效率是最高的。


合并小文件的方式主要有两种:

1. 将小文件归档成har文件

2. 用MR程序将小文件合并

对于第一种方法,归档成har包方法具体如下:

  1.生成归档文件  

        hadooparchive -archiveName test.har -p /sourcePath /destPath

        2. 查看归档之后的文件

    hadoop dfs -ls /destPath

3. 查看归档之前的文件

    hadoop dfs -ls har:///destPath

4. 归档文件也可以像归档之前文件一样进行后续的mapreduce程序的计算

        hadoopjar hadoop-examples-1.0.3.jar wordcount har:///tmp/aaa.har/* /tmp/wordcount2


对于第二种方法,自己写了一个根据输入的目录大小判断最终生成多少个reduce的方法,reduce的个数,也就是最终的文件数量。


#!/bin/bash

block=2147483648; #2G

#check input param num
if [[ $# -ne 2 ]]
then
        echo "the usage of this script is:";
        echo $'\t sh merge.sh ';
        exit 1;
fi

#check input input and output path
if `hadoop dfs -test -e $1`
then
        if `hadoop dfs -test -e $2`
        then
                echo "the has already exist, please choose anther and try again!";
                exit 1;
        else
                #do the merge
                size=`hadoop dfs -dus $1 | awk -F" " '{print $2}'`;
                num=`expr $size / $block`;
                if [[ $num -eq 0 ]]
                then 
                        num=1;
                fi
                hadoop jar inputtooutput.jar com.InputToOutput.InputToOutput           \
                       -D input_dir=$1                                                 \
                       -D output_dir=$2                                                \
                       -D reduce_num=$num
                if [[ $? -eq 0 ]]
                then 
                        #delete source path
                        hadoop dfs -rmr $1 >/dev/null
                        #mv des path to source path
                        hadoop dfs -mv $2 $1;
                        if [[ $? -eq 0 ]]
                        then 
                                echo "merge success!";
                        fi
                fi
        fi
else
        echo "the is not exist, please check and try again!";
        exit 1;
fi

用到的jar包在附件中

你可能感兴趣的:(Hadoop相关)