【Hadoop】HDFS小文件处理

HDFS在处理大量小文件时面临元数据管理和计算效率挑战,如内存消耗过大及MapReduce作业慢。解决方法包括使用archieve归档、Sequence Files和CombineInputFormat,但各有优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为什么需要在HDFS中处理小文件?(为什么HDFS不适合处理大量的小文件)

  1. 在HDFS中,每一个block,文件夹或者目录都占用150字节的内存。无论为一个block的大小为1KB或者128MB,都将占用128MB的内存。在HDFS中存储大量的小文件意味着Namenode中需要存储大量的block元数据。由于Namenode的内存是有限的,在集群中存储大量的小文件可能导致内存很快被消耗完。
  2. 在mapreduce计算阶段,由于maptask的数量等同于一个job中输入数据的切片数量(block数量)。如果输入数据是大量的小文件,就需要开启大量的maptask来映射数据。每开启一个maptask都需要启动一次JVM,从来带来大量JVM启动开销。最终导致job需要花费更多的的时间

如何解决?

  1. archieve归档(har文件)
#将一些小文件归档成har文件,对外为一个整体,对内依然为一些小文件
$ bin/hadoop achieve -achievename 文件名.har -p src dst

#解归档
$ hadoop fs -cp har://src/文件名.har/* dstsrc

#原始的小文件需要手动删除,har文件不可修改
#若要删除har文件,只能通过-rmr
$ hadoop fs -rmr src/文件名.har

#har文件作为mapreduce阶段的的输入数据
$ hadoop jar包 har://src/文件名.har/* dst

该方法在一定程度上节约了Namenode的内存。但在mapreduce计算阶段,依然按照原始的小文件切片,需开启大量的maptask。

  1. Sequence Files:文件名作为key,文件内容作为value
public static void seqFileWrite(String[] args) throws IOException {

        Text key = new Text();
        BytesWritable value = new BytesWritable();

        //获取配置对象
        Configuration conf = new Configuration();

        //输出路径及文件名(.seq类型)
        Path dst = new Path(args[0]);
        SequenceFile.Writer.Option optionPath = SequenceFile.Writer.file(dst);

        //配置kv类型
        SequenceFile.Writer.Option optionKey = SequenceFile.Writer.keyClass(key.getClass());
        SequenceFile.Writer.Option optionValue = SequenceFile.Writer.valueClass(value.getClass());

        //获取writer
        SequenceFile.Writer writer = SequenceFile.createWriter(conf, optionPath, optionKey, optionValue);

        //输入路径
        File src = new File(args[1]);

        //循环读取文件并写入
        for (File file : src.listFiles()) {

            //封装kv
            key.set(file.getName());
            value.set(FileUtils.readFileToByteArray(file), 0, FileUtils.readFileToByteArray(file).length);

            //写入kv
            writer.append(key, value);

        }

        //关闭资源
        IOUtils.closeStreams(writer);  //writer.close();

    }
 public static void seqFileRead(String[] args) throws IOException {

        //配置文件对象
        Configuration conf = new Configuration();

        //Reader配置
        //读取路径
        Path src = new Path(args[0]);
        SequenceFile.Reader.Option optionPath = SequenceFile.Reader.file(src);

        //获取Reader
        SequenceFile.Reader reader = new SequenceFile.Reader(conf, optionPath);

        //获取kv类型
        Writable key = (Writable) ReflectionUtils.newInstance(reader.getKeyClass(), conf);
        BytesWritable value = (BytesWritable) ReflectionUtils.newInstance(reader.getValueClass(), conf);


        while (reader.next(key, value)) {

            //打印kv
            System.out.println(key);
            String decode = Text.decode(value.getBytes());  //BytesWritable转换为Text类型
            System.out.println(decode);

        }

        //关闭资源
        IOUtils.closeStream(reader);  //reader.close();

    }
  1. CombineInputFormat
CombineTextInputFormat.setMaxInputSplitSize(job, 1024 * 1024 * 128);  //128MB
job.setInputFormatClass(CombineTextInputFormat.class);
  1. 开启JVM宠用
#mapredu-site.xml
<property>
	<name>mapred.job.reuse.jvm.num.tasks</name>
	<value>-1</value>
</property>

引用:
解读:Hadoop Archive
The Small Files Problem

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值