小文件处理专题

小文件处理专题

一 MapReduce

1.1 小数据带来的问题

  1. 在HDFS上,每个文件在NameNode上占150Byte(在内存中占用),如果小文件过多的话就占用大量的Namenode内存,并且查找元数据的速度会很慢
  2. 在处理MapReduce的过程中每一个小文件就要启动切一片,并且要启动一个maptask,每个maptask默认内存是1G,这样会大量消耗NodeManager内存,同时一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。

1.2 如何解决

  1. 数据源头解决,如果是在flume传输数据进入HDFS的时候控制文件滚动参数,或者使用hbase数据库存储流失数据进行定期合并

    ## 不要产生大量小文件(滚动策略,按照时间滚动,文件大小滚动,数据条数)
    a1.sinks.k1.hdfs.rollInterval = 3600
    a1.sinks.k1.hdfs.rollSize = 134217728
    a1.sinks.k1.hdfs.rollCount = 0
    
  2. 存储在hdfs上可以通过har归档的方式合并小文件,但是只能解决NameNode内存问题,对于MapReduce 来说起不到任何作用,因为har文件就相当一个目录,仍然不能讲小文件合并到一个split中去,一个小文件一个split ,任然是低效的

  3. MR时:

    1. MR输入时可以使用combineinputformat的方式通过设置合并小文件的大小

      // 如果不设置InputFormat,它默认用的是TextInputFormat.class
      job.setInputFormatClass(CombineTextInputFormat.class);
      //虚拟存储切片最大值设置4m
      CombineTextInputFormat.setMaxInputSplitSize(job, 134217728);
      
    2. 开启uber模式,实现jvm重用,默认每个task任务占用一个jvm,使用完之后就会释放,其他task需要重新申请,如果task结束不释放jvm,让另一个task继续使用,就会节省task申请jvm的时间

      https://blog.csdn.net/myproudcodelife/article/details/44477819 uber模式,jvm使用详解,1.X支持重用,2.X支持uber

      JVM重用可以使得JVM实例在同一个job中重新使用N次,N的值可以在Hadoop的mapred-site.xml文件中进行配置。通常在10-20之间

      <property>
      
        <name>mapreduce.job.jvm.numtasksname>
      
        <value>10value>
      
        <description>How many tasks to run per jvm,if set to -1 ,there is  no limitdescription>
      property>  
      

      **弊端:**开启JVM重用时,task用过的插槽会一直被占用,直到整个查询任务结束,插槽才会被释放

    3. 调优,不仅仅是叫理解调优之后的值,调优是遇到一些特殊场景再调优,一般情况是采用默认值,参数调优就是把默认值改了,默认值就是应对大部分场景下的情况,调优应对的是特殊情况。

二 hive

2.1 hive小文件是如何产生的

  1. 动态分区:hive支持的动态分区功能很强大,可以根据字段自动分区,但是如果分区字段的数值种类过多的话就会在hdfs产生很多的小文件,导致hive在MR的时候处理过多的小文件
  2. reduce过多,每一个reducetask默认输出一个文件
  3. 数据源本身就含有大量小文件

2.2 小文件的危害:

​ 同hadoop的MR一样

2.2 如何解决

  1. 使用Hadoop achieve把小文件进行归档

  2. 重建表,建表时减少reduce的数量(也就是减少分区数的产生)

    distribute by 字段名,cast(rand(),123) --重建表
    
  3. 在hive程序运行之前设置参数合并小文件

//每个Map最大输入大小(这个值决定了合并后文件的数量)
set mapred.max.split.size=256000000;  
//一个节点上split的至少的大小(这个值决定了多个DataNode上的文件是否需要合并)
set mapred.min.split.size.per.node=100000000;
//一个交换机下split的至少的大小(这个值决定了多个交换机上的文件是否需要合并)  
set mapred.min.split.size.per.rack=100000000;
//执行Map前进行小文件合并
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; 
  1. 设置map输出和reduce输出进行合并的相关参数调整map和reduce的数量
//设置map端输出进行合并,默认为true
set hive.merge.mapfiles = true
//设置reduce端输出进行合并,默认为false
set hive.merge.mapredfiles = true
//设置合并文件的大小
set hive.merge.size.per.task = 256*1000*1000
//当输出文件的平均大小小于该值时,启动一个独立的MapReduce任务进行文件merge。
set hive.merge.smallfiles.avgsize=16000000

三 spark

  1. spark处理小文件:

    主要是通过repartition和coalesce减少分区达到处理小文件的效果

    1. repartition默认使用shuffle,一般使用这种
    2. coalesce默认使用不使用shuffle,有可能会产生数据倾斜
  2. sparkSQL设置reduce的读取目标数据量

    val sc = new SparkContext(conf)
    val hiveContext = new HiveContext(sc)
    --启用Adaptive Execution,从而启用自动设置Shuffle 
    hiveContext.setConf("spark.sql.adaptive.enabled","true")
    --设置每个Reducer读取的目标数据量,默认64M,一般改成集群块大小
    hiveContext.setConf("spark.sql.adaptive.shuffle.targetPostShuffleInputSize","128000000")
    
  3. https://blog.csdn.net/a13705510005/article/details/102295768 spark具体的小文件场景以及解决办法

  4. 算子也可以调整分区

你可能感兴趣的:(大数据优化专题,大数据)