> 技术文档 > 数据开发之八股整理 : 四. Hadoop小文件优化方法_hdfs优化 小文件 namenode元数据

数据开发之八股整理 : 四. Hadoop小文件优化方法_hdfs优化 小文件 namenode元数据


四. Hadoop小文件优化方法

在Hadoop中,小文件(Small Files)是指远小于HDFS块大小(通常为128MB或256MB)的文件。当大量小文件存储在HDFS中,会引发一系列性能和资源管理问题,因此需要进行优化。


(一) 为什么要优化小文件问题?

  1. NameNode内存压力大
    Hadoop 的 HDFS 使用 NameNode 存储文件元数据(如文件名、块位置、权限等)。一个block的元数据的大小约为150byte,过多小文件会产生很多的元数据文件,一方面导致 NameNode 内存占用过高,另一方面元数据文件过多会使得寻址速度变慢。

  2. 任务调度效率低
    小文件过多,在进行MR计算时,会生成过多切片,需要启动过多的map task,每个map task处理的数据量小,导致map task的处理时间比启动时间还小,白白消耗资源。

  3. I/O 效率低
    每次读取一个小文件都涉及一次网络或磁盘 I/O,频繁的 I/O 操作比一次性读取大文件的效率要低很多


(二) Hadoop 小文件的优化方法

1. 合并小文件 (数据源头)

在数据采集的时候, 就将小文件或小批数据合并成大文件再上传HDFS。

2. 使用 HAR 文件(Hadoop Archive)(存储方向)

Hadoop Archive(简称 HAR 文件)是一种 Hadoop 提供的机制,用于优化大量小文件在 HDFS 上存储和访问的问题。它通过将多个小文件打包成一个归档文件,从而减少 NameNode 的元数据负担,提高整体系统的性能和可扩展性。


假设你有下面这些小文件:

/user/hadoop/input_small_files/├── file1.txt (1KB)├── file2.txt (2KB)├── file3.txt (3KB)...共 10,000 个文件,每个不到10KB

这些小文件分别作为一个 HDFS 文件,会造成 NameNode 元数据管理 10,000 条记录,非常消耗内存。

现在你使用 HAR 进行归档:

hadoop archive -archiveName mydata.har -p /user/hadoop/input_small_files /user/hadoop/output_archive/

归档结果目录如下:

/user/hadoop/output_archive/└── mydata.har/ ├── _index  # 索引所有小文件的偏移 ├── _masterindex # 加速索引查找 ├── part-0  # 所有小文件的数据打包在这

HDFS 现在只看到 3 个大文件,从而只记录 3 条元数据项。访问其中的 file2.txt 时,系统查索引并从 part-0 中精确提取它的字节范围返回给用户。

也即: 

HDFS 原始:- file1.txt(128B) -> block1- file2.txt(256B) -> block2- ... -> 占据大量元数据使用 HAR 后:- _index (索引所有文件的起止偏移)- _masterindex(记录索引的索引)- part-0 (数据区,连续存储所有小文件数据)访问 file1.txt:- masterindex -> index -> part-0 offset 0-128B

3. CombineTextInputFormat (计算方向)

CombineTextInputFormat 是 Hadoop 提供的一种 输入格式(InputFormat),它的主要作用是解决 MapReduce 中小文件过多导致 map 任务数量激增、性能下降的问题

(1) 是什么

CombineTextInputFormatTextInputFormat 的一个子类,作用是:

将多个小文件组合成一个逻辑分片(InputSplit),使得多个小文件可以被 一个 map task 处理

它仍然以“行”为单位读取文本数据,只是将多个文件合并为一个逻辑输入来减少 task 数量。

(2) 工作机制
小文件: file1.txt (5MB) file2.txt (10MB) file3.txt (7MB) ... file1000.txt (2MB)默认方式: file1.txt -> split1 -> Map1 file2.txt -> split2 -> Map2 ... file1000.txt -> split1000 -> Map1000 ▶ 启动 1000 个 map task使用 CombineTextInputFormat: CombineSplit1 = [file1.txt, file2.txt, file3.txt] -> Map1 CombineSplit2 = [file4.txt, file5.txt, file6.txt] -> Map2 ... ▶ 将多个小文件合并成一个逻辑分片,显著减少 Map 数量

更详细的工作机制见(三) - 4 - (4): 数据开发之八股整理 : 二. MapReduce相关内容_-d mapreduce.job.timeout=60000-CSDN博客

4. 开启uber模式, 实现JVM重用

(1) 什么是uber模式

Uber 模式(Uber AM execution mode)是指:

将 MapReduce 作业的所有任务(map 和 reduce)都在 ApplicationMaster(AM)容器中执行,不再单独为每个 task 启动 container。

这是一个轻量级的执行模式,适用于小规模任务,尤其是处理小文件的数据分析、ETL、预处理任务等。

普通模式 vs Uber 模式 对比:

阶段 普通模式 Uber 模式 MapTask 启动 每个 split 启动一个 container 所有 map 任务在 AM 内运行 ReduceTask 启动 每个 reduce 启动一个 container 所有 reduce 任务在 AM 内运行 调度开销 高(需启动多个容器) 低(只需一个 AM 容器) 资源隔离 好 差,但性能快 启动时间 慢 快
(2) Uber 模式执行流程
  1. 提交作业;

  2. YARN 启动 ApplicationMaster;

  3. AM 检查作业大小是否符合 Uber 条件(小 map 数、小输入、小资源需求);

  4. 如果满足条件,AM 自己完成所有 map 和 reduce 任务的执行;如果不满足条件,不启动uber模式;

  5. 返回结果,释放资源。

是否实际启用 Uber 模式,需要输入同时满足约束条件,以下参数可以自行配置, 包括:

参数 含义 默认值 如果不满足 mapreduce.job.ubertask.maxmaps 允许的最大 map task 数 9 超过就不启用 mapreduce.job.ubertask.maxreduces 最大 reduce 数 1 超过就不启用 mapreduce.job.ubertask.maxbytes 最大输入数据大小(单位:byte) 128MB 超过就不启用 mapreduce.job.ubertask.maxram 最大内存使用 1GB 超过就不启用