CombineTextInputFormat小文件处理场景

存在的问题

HDFS设计是用来存储海量数据的,特别适合存储TB、PB量级别的数据。但是随着时间的推移,HDFS上可能会存在大量的小文件,这里说的小文件指的是文件大小远远小于一个HDFS块(128MB)的大小;HDFS上存在大量的小文件至少会产生以下影响:

消耗NameNode大量的内存

延长MapReduce作业的总运行时间

因为MapReduce框架默认的 TextInputFormat 切片机制是对任务按文件规划切片,如果有大量小文件,就会产生大量的 MapTask,处理小文件效率非常低。

解决方案

Hadoop内置提供了一个CombineTextInputFormat类来专门处理小文件,其核心思想是:根据一定的规则,将HDFS上多个小文件合并到一个 InputSplit中,然后会启用一个Map来处理这里面的文件,以此减少MR整体作业的运行时间。

CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 4m

切片机制过程

CombineTextInputForma切片机制过包括:虚拟存储过程切片过程二部分

假设 setMaxInputSplitSize 值为 4M,有如下四个文件

a.txt 1.7M

b.txt 5.1M

c.txt 3.4M

d.txt 6.8M

(1)虚拟存储过程

(1.1)将输入目录下所有文件大小,依次和设置的 setMaxInputSplitSize 值比较,如果不大于设置的最大值,逻辑上划分一个块。

(1.2)如果输入文件大于设置的最大值且大于两倍,那么以最大值切割一块,当剩余数据大小超过设置的最大值且不大于最大值2倍,此时将文件均分成2个虚拟存储块(防止出现太小切片)。

1.7M < 4M 划分一块

5.1M > 4M 但是小于 2*4M 划分二块:块1=2.55M,块2=2.55M

3.4M < 4M 划分一块

6.8M > 4M 但是小于 2*4M 划分二块:块1=3.4M,块2=3.4M

最终存储的文件:

1.7M

2.55M,2.55M

3.4M

3.4M,3.4M

(2)切片过程

(2.1)判断虚拟存储的文件大小是否大于 setMaxIputSplitSize 值,大于等于则单独形成一个切片。

(2.2)如果不大于则跟下一个虚拟存储文件进行合并,共同形成一个切片。

最终会形成3个切片:

(1.7+2.55)M,(2.55+3.4)M,(3.4+3.4)M

代码举例:

main方法中:

job.setInputFormatClass(CombineTextInputFormat.class);
        CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 4m
2
1
        job.setInputFormatClass(CombineTextInputFormat.class);
2
        CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 4m

总结:

CombineTextInputFormat 小文件处理场景

  • 默认读取数据机制的弊端
  • 默认TextInputFormat 逐个遍历文件 意味着不管文件多大 至少自己本身都是一个切片
    如果小文件过多 势必会形成很多个切片 就会启动多个maptask 浪费资源。
  • CombineTextInputFormat
    • 设置一个切片的最大值 
    • CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 4m
      
    • 首先,虚拟存储过程
    • 遍历每一个小文件 跟设置值进行比较
      如果小于 自己本身就是一个
      如果大于 不超过2倍 就把该文件平均
      如果大于 超过2倍 就按照最大值切
    • 然后,切片规划的过程
    • 上一步虚拟存储的结果 逐个判断 如果不超过设置的值 就和后面的合并 合并之后如果依然没超过,继续合并 直到超过设置最大值。形成切片。
      
    • 针对小文件 ,最佳的处理方式 还是上传hdfs之前进行合并,目标--->block size

### MapReduce 统计失败原因及解决方法 #### 一、路径相关问题 路径书写错误是导致 MapReduce 程序运行失败的主要原因之一。如果程序无法找到指定文件,通常是因为路径设置不正确或者存在多余的扩展名。例如,在某些情况下,`pd.txt.txt` 这样的命名可能导致读取失败[^3]。建议检查输入和输出路径是否正确配置,并尝试使用绝对路径替代相对路径。 #### 二、数据格式问题 在执行 WordCount 或其他基于文本处理的任务时,输入数据的格式可能不符合预期标准。这可能会引发解析错误或其他异常情况。确保输入文件中的每一行都是有效的字符串形式,避免特殊字符干扰正常流程[^2]。 #### 三、类库导入问题 开发过程中经常遇到因缺少必要依赖项而导致编译或运行时报错的情况。特别是当涉及到 `Text` 类型以及 `CombineTextInputFormat` 的时候更容易出现问题。需要注意的是 Mapper 方法的第一个参数应该是 `LongWritable` 而不是 `IntWritable` ,否则会出现类型转换方面的错误提示信息指出具体位置所在之处即为上述提到过的两个地方之一[^4]。 #### 四、内存溢出与资源分配不足 对于大规模数据集来说,合理调整 JVM 堆大小和其他 Hadoop 参数至关重要。可以通过增加 mapred.child.java.opts 属性值来提高单个 tasktracker 子进程可用的最大堆空间;另外还可以通过优化 combiner 函数减少中间结果传输量从而降低整体消耗水平达到提升性能目的同时也能有效防止 OOM (Out Of Memory) 错误发生几率下降明显效果显著可见一般推荐做法如下所示: ```bash export HADOOP_HEAPSIZE=2048 set mapreduce.map.memory.mb=1536; set mapreduce.reduce.memory.mb=2048; ``` 以上命令分别设置了Hadoop服务端最大允许使用的Java heap size为2GB, 同时也将mapper/reducer任务各自所能占用的最大物理RAM数量设为了适当数值以适应不同规模的工作负载需求场景下的高效稳定运作状态. --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值