MapReduce运行基本原理

一.FileInputFormat逻辑切片

1.程序获取数据目录

2.遍历目录下的文件,每个文件单独切片

3.开始处理文件:

a.获取文件的大小

b.计算逻辑切片,默认split size=block size=128M,从下面源码中可以解析出 Math.Max(minsize,Math.Min(maxsize,blocksize)),minsize默认大小为1字节,maxsize默认大小为2G,上面的公式就默认了系统的逻辑切片大小就是块的大小。要改变切片的大小只需要更改Minsize或者maxsize。代码实现如下:在job中更改Configuration的配置。

Configuratition conf =new Configuration();

conf.set("mapreduce.input.fileinputformat.split.minsize","自定义大小")

conf.set("mapreduce.input.fileinputformat.maxsize","自定义大小") 

只要更改其中任意一个参数,就可以实现切片大小的变更。

4.切片的数量决定了map的数量,一个切片对应一个maptask进程,所以通过变更切片的size就可以改变Map的数量。在多节点的服务器上,map越多,效率越高,并发强。但是在正常生产中,不会更改map的数量,都是按照默认配置。

5.每次切片后,都会判断剩余的切片大小是否大于块的1.1倍,如果不大于,就划分为一个切片。

6.切片信息会保存在切片规划文件中

7.整个逻辑切片的核心流程都是在getsplit()方法中实现的,返回的是Inputsplit的集合。集合中存储的是元数据信息,包括起始偏移量,长度,节点列表等。整个过程都只是逻辑切片,并不是真正意义上的物流切割。

8.最后提交切片规划文件给Yarn,MrAPPMaster通过提交的规划文件计算出maptask的数量。

二.MapTask阶段

1.read阶段

开启maptask进程,通过TextInputFormat抽象类调用recoderreader()方法里的LineReader()方法来读取数据,每次读取一行,一行的默认大小为64KB,每次找\n换行符作为每行的结束符,返回(k,v)键值对,k是起始偏移量,v是一行的数据。一行的大小可以通过人为的代码更改,代码如下:在Job中更改Confuguration配置

Configuration conf =new Configuration();

conf.set("io.file.buffer.size","自定义大小")

2.map阶段

上面得到的(k,v)键值对,通过调用mapper里面的map()方法进行逻辑处理,生成新的(k,v)键值对,通过context.write()方法输出到outputcollector收集器。

3.collect收集阶段

a.OutputCollectot收集器会把收集到的(k,v)键值对写入到环形缓冲区中,环形缓冲区默认大小为100M,每次写80%(环形缓冲区就是环形数组,前面写着,后面组件清理着,写入文件,防止溢出)。当达到80%的时候,就会触发spill溢写(80%是为了让环形缓冲区高速运转,效率高)。

b.shuffle是MR中的一个过程(从map产生输出开始到reduce取得数据作为输出之前的过程),它的每个处理步骤都是在各个maptask和reducetask节点上完成的,整体分三个操作

①.partition 分区,默认为hash分区,也可以自己定义分区规则,主要对这些数据进行归类,可以通过key映射给不同的reduce

②.sort对Key进行排序(快排+归并)

③.combinner进行局部的value合并,即写入文件前,对每个分区的数据进行一次聚集操作

4.溢写阶段

a.在spill溢写前,先对数据进行分区和排序(快排),即会对环形缓冲的(k,v)键值对hash一个partition值,相同的partition值分为一个区,然后把环形缓冲区的数据跟partition值和key进行升序排列,同一个partition分区的key是有序的。

b.将环形缓冲区排序后的内存数据不断溢写到本地磁盘上,如果前期处理的Map数据量大,可能会产生多个溢写文件。

5.merge阶段

多个溢写文件会merge合并成一个大的文件,以确保最终每个maptask只有一个大文件,合并采用归并排序的算法,所以合并的大文件最终是分区且区内有序的。保存文件在output/file.out中。同时生成相应的索引文件output/file.out.index。

三.Reduce阶段

1.copy阶段

每个reducetask会跟根据自己的分区号去对应的maptask上面copy对应的partition分区数据,这些数据会保存在内存的缓冲区中,当内存缓冲区达到一定阀值,会保存在reducetask本地磁盘上。

2.sort+merge阶段

reduce会把同一分区下的来自不同maptask的结果文件,进行merge合并成一个大文件(归并排序),key有序。

3.reduce阶段

a.在合并成大文件后,shuffle的进程也就结束了,后面进入reducetask的逻辑处理阶段。首先调用GrouppingComparator对大文件进行分组,从文件中取出每个(key,values)键值对,调用用户的自定义的reduce方法进行逻辑处理。

b.最后调用OutputFormat方法将结果数据写入到结果文件中。

四.MapReduce执行效率优化

shuffle中的环形缓冲区大小会影响到mapreduce程序的执行效率,原则上说,缓冲区越大,磁盘的IO的次数越少,执行的速度越快。环形缓冲区的大小可以通过在mapred-site-xml中设置mapreduce.task.io.sort.mb的值来改变,默认为100M。溢出的时候调用combiner组件,逻辑和reduce的一样,合并相同的key,value相加,这样的效率高,不用一下子传好多相同的Key,在数据量非常大的时候,这样的优化可以节省很多网络带宽和本地磁盘IO流的读写,具体的代码实现:定义一个combiner类,继承Reducer,输入类型和map的输出类型相同。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值