Day39~40_Hadoop之MapReduce(二)

四、MapReduce框架原理

(一)InputFormat(顶级抽象类)数据输入

1、切片与MapTask并行度决定机制

我们在指定driver类的main方法向yarn提交任务时,需要提前把输入数据进行切片,那么数据切片和Hdfs的切块有什么区别呢?

数据块:Block是HDFS物理上把数据分成一块一块。

数据切片:数据切片只是在逻辑上对输入的文件进行按数据大小进行划分成几部分,并不会物理上将文件切分。

默认情况下,切片的数量决定着MapTask的数量,而MapTask的并行度又决定着Map阶段的任务处理的并发度,是不是并发度越高处理速度越快呢?答案是否定的,这又与文件数量与文件大小息息相关。

比如:有一个500M的文件,将会启用4个MapTask,这样会提高数据的处理速度,那么有4个1Kb的文件,也启用4个MapTask会提高处理速度吗?

2、job提交及切片源码解析

       (1)执行job提交:job.waitForCompletion() 或者 job.submit()

 

    (2)job提交过程

            a. 在JobSubmitter类中调用submitJobInternal()

 

    b. 通过submitJobInternal()调用writeSplits(),在writeSplits()中调用writeNewSplits(),在writeNewSplits()中调用getSplits(job)

   c. 而getSplits()是InputFormat抽象类的抽象方法,需要被子类FileInputFormat进行实现

d. 进入到FileInputFormat,查看getSplits()方法,其中有做某个文件是否需要被切片处理的判断(红线标注处),且常量SPLIT_SLOP = 1.1

 

e. 返回JobSubmitter类的submitJobInternal()方法,最后是提交job并返回JobStatus对象(根据jobid返回作业运行过程中的各种状态信息)

    流程图如下:

3、FileInputFormat(抽象类)切片机制

我们默认的切片类是FileInputFormat,下面看下FileInputFormat的切片机制是怎样工作的。

(1)根据driver中设置的输入目录,找到你数据存储的目录。

    (2)开始遍历处理目录下的每一个文件(规划切片)

    (3)遍历第一个文件xx.txt

       a)获取文件大小fs.sizeOf(xx.txt)

b)默认情况下,切片大小=blocksize

       c)开始切,例如有个300M的文件。形成第1个切片:ss.txt—0:128M 第2个切片:ss.txt—128:256M 第3个切片:ss.txt—256M:300M(每次切片时,都要判断切完剩下的部分是否大于块的1.1倍,不大于1.1倍就划分一块切片) 。 剩下部分大于128m但是小于140m。

       d)将切片信息写到一个切片规划文件中

e)数据切片只是在逻辑上对输入数据进行分片,并不会再磁盘上将其切分成分片进行存储。使用InputSplit只记录了分片的元数据信息,比如起始位置、长度以及所在的节点列表等。

f)注意:block是HDFS物理上存储的数据,切片是对数据逻辑上的划分。

    (4)提交切片规划文件到yarn上,yarn上的MrAppMaster就可以根据切片规划文件计算开启MapTask个数。

4、CombineTextInputFormat切片机制

关于大量小文件的优化策略:

默认情况下TextInputformat对任务的切片机制是按文件规划切片,不管文件多小,都会是一个单独的切片,都会交给一个MapTask,这样如果有大量小文件,就会产生大量的MapTask,处理效率极其低下。

(1)优化策略

a)        最好的办法,在数据处理系统的最前端(预处理/采集),将小文件先合并成大文件,再上传到HDFS做后续分析。

b)        补救措施:如果已经是大量小文件在HDFS中了,可以使用另一种InputFormat来做切片(CombineTextInputFormat),它的切片逻辑跟TextFileInputFormat不同:它可以将多个小文件从逻辑上规划到一个切片中,这样,多个小文件就可以交给一个MapTask。

c)        虚拟存储切片最大值设置

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

   注意:虚拟存储切片最大值设置最好根据实际的小文件大小情况来设置具体的值。

d)        切片机制

虚拟存储过程:

将输入目录下所有文件大小,依次和设置的setMaxInputSplitSize值比较,如果不大于设置的最大值,逻辑上划分一个块。如果输入文件大于设置的最大值且大于两倍,那么以设置的最大值切割一块(逻辑上的切割);当剩余数据大小超过设置的最大值且不大于最大值2倍,此时将文件均分成2个虚拟存储块(防止出现太小切片)。

例如setMaxInputSplitSize值为4M,输入文件大小为8.02M,则先逻辑上分成一个4M。剩余的大小为4.02M,如果按照4M逻辑划分,就会出现0.02M的小的虚拟存储文件,所以将剩余的4.02M文件切分成(2.01M和2.01M)两个文件。

切片过程:

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

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

(c)测试举例:有4个小文件大小分别为1.7M、5.1M、3.4M以及6.8M这四个小文件,则虚拟存储之后形成6个文件块,大小分别为:

1.7M,(2.55M、2.55M),3.4M以及(3.4M、3.4M)

最终会形成3个切片,大小分别为:

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

(2)具体实现步骤

//  如果不设置InputFormat,它默认用的是TextInputFormat.class

job.setInputFormatClass(CombineTextInputFormat.class);

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

5、CombineTextInputFormat案例实操

(1)        需求

将输入的大量小文件合并成一个切片统一处理。

(2)输入数据

准备5个小文件

(3)实现过程

        a)不做任何处理,运行需求1中的wordcount程序,观察切片个数为5,如下图所示:

        b)在WordcountDriver中增加如下代码,运行程序,并观察运行的切片个数为1,如图所示

// 如果不设置InputFormat,它默认用的是TextInputFormat.class
job.setInputFormatClass(CombineTextInputFormat.class);
CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 4m

6、FileInputFormat实现类

    FileInputFormat常见的接口实现类包括:TextInputFormat、KeyValueTextInputFormat、NLineInputFormat、CombineTextInputFormat等。

除了以上实现类,我们还可以自定义InputFormat。

        (1)TextInputFormat

       TextInputFormat是默认的FileInputFormat实现类,是按行的方式进行读取数据,读取出来的数据被处理成(K,V)的方式。K键是存储该行在整个文件中的起始字节偏移量, 是LongWritable类型。V值是这行的内容,不包括任何行终止符(换行符和回车符),是Text类型。

    比如:

文本内容为:
		    hadoop spark
		    spark
		    hello world
		    hello
		TextInputFormat读取每行内容后处理为键值对:
		    (0,hadoop spark)
(14,spark)
(21, hello world)
(34,hello)

(2) KeyValueTextInputFormat

    每一行均为一条记录,被分隔符分割为key,value。可以通过在驱动类中设置conf.set(KeyValueLineRecordReader.KEY_VALUE_SEPARATOR

, "\t");来设定分隔符。默认分隔符是tab(\t)。

    比如:

文本内容为:(”->”是Tab制表符)
zhangsan->15->male
lisi->17->male
wangwu->16->female
	  KeyValueTextInputFormat读取每行内容后处理为键值对:
		 ࿰
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值