00:00
好,接下来呢,我们先讲一下这个MAP6工作流程啊,呃,先从整体上那大家有一个概念性的了解,那这里面一些细节呢,我我们后面呢,再讲这个啊,这些内容的时候呢,会给大家详细的去讲,包括这里面的分区啊,啊排序啊,以及合并啊,还有这个输出相关的一些事情啊,再给大家介绍,但是呢,先让大家知道这个MAP60工作流程当中有哪些,嗯,大体的这个功能对吧?哎,我们来看一下啊。第一步,首先呢,我们这里面哎,准备了一个待处理的输入文件,叫送送点T,那它的大小呢,是200兆,没问题吧,哎,200兆,然后呢,我们对它进行一个切片分析。这个灯刚才我们也看过源码,那在这个submit里面就会对这个原始数据进行一个切片,比如说送送点T0~128啊,128兆是一片,那剩下的128~200是第二片,OK。接下来。
01:00
他会这个客户端啊,会准备三样东西。对这个集群进行提交,哪三样呢?分别是job的切片。架包以及呢参麦喽,如果你是本地模式,那这里面没有这个架包,因为我们正常生产环境下用的都是这种雅安集群模式,所以说这个架包呢也是有的,那切片不用说了啊,这个XML呢,是这个job运行相关的参数好。那这个客户端向雅恩提交,提交完之后,那雅恩会干什么事呢?他会开启一个Mr APP master。还记得他是谁吗?他是整个任务运行的老大。对吧,哎,那他就会去读取客户端对应的信息,他最主要的读的就是它。读取你的切片信息,读它有什么用呢?它会根据你提供的切片个数。对应的开启map t的个数,那咱这里面很显然我是两个切片,那我就对应的开启两个map t,诶这个是零到128,这是128~200。
02:07
那我们呢,就一个map test,诶给大家详细的去剖析,因为另一个他们运行的逻辑都是一样的,对吧,好。那这个map task1启动之后,它就开始工作了,他用谁来去读这里面输入的文件呢?它有一个input。默认的呢,是test。步发里面有两个方法,还记得吧,一个叫record reader,另一个呢,是isliable,你说是否可以切割?好啊,那record reader里面还记得test in important,他的record reader是什么样的吗?是lineon record reader也是按行去读取,哎,读这里面内容,那读的话,读完之后它的K是什么,为什么。K是对应的偏移量,V呢,就是这一行内容是这样吗?哦,你说由它来读太音普曼读完之后,那读完之后返回给谁呢?
03:05
思考一下他去读,读完之后给谁。我们在之前代码里是不是就直接给到这个map啊。对吧,因为我们这个map的输入是不是就是KV啊,哎,K呢是偏移量,V呢是一行内容,哎,他读完之后就给到他。给到他之后,这里面是我们用户自己写的业务逻辑。根据你的需求,你是统计word count呀啊,还是统计这个手机号啊等等相关信息,那是你根据业务逻辑来写。好,那我们用户写完之后,这个数据输出到哪儿了呢。那我没讲这个课之前,有没有同学说这个直接就到reduce了,有没有这种想法了啊,其实啊,他在离reduce这个过程当中,这个距离啊还有很远。啊,那看一下中间他干了什么事啊,这是一个output c啊,是一个输出的收集器,我们也叫它呢,环形缓冲区。
04:02
所谓的还原缓冲区呢,它就是一块内存。哎,你可以把它当成内存就行了,那这个内存呢,它是有点特点的,什么特点呢?它的内存呢,一半用来存数据,那在右侧存了数据KV对吧,偏移量和行的内容,那左侧存储呢,叫索引。哎,叫索引,什么叫索引呢?哎,就是描述数据的数据叫原数据,比如说描述这个数据的原数据。什么叫描述这个数据源数据呢?你看啊,这个原数据,这是实实在在的数据,实实在在的数据里面有KUV好。我用来描述你什么呢?你的索引对吧,Index从零开始,0123往后编,编号没问题吧,那再来你这个数据是哪一个分区的。哎,分区还记得吗?对吧,那比如说咱们之前是呃,ABCDA到H啊,什么什么G到这个这啊类似的这样,那这一个这一块啊放到一起,这一块放到一起啊,这样的一个分区啊好。
05:02
那再来key start key start什么含义啊,你这是数据,Key start是不是在内存当中,你存储在什么位置啊?哎,那我这里面就是,哎,你比如说你从零开始。那另一个呢,是Y62的,那假如说Y62到十。那我这个K啊,就是从零到十,那Y6怎么定位,它存储在哪呢?那Y6的话,假如说那你下一个K的开始位置是20。那我这个Y流不就十到20吗?那再来,那呃,它还有自己的V,哎,这样呢,就能把所有的这个数据啊定位出来,这是标记数据存储在哪。这里呢是分区,这是索引。那行,那我这个叫环形缓冲区,环形缓冲区多大呢。它的默认大小啊是100兆。啊,默认是100兆,那它到达80%的时候,进行反向一写啥意思,它正常这个数据啊,是这样从这开始写,左侧呢存索引,右侧纯数据写,他写到80%的时候。
06:04
它就停了,它就不再往前写了,他会找这两个的中间位置。还剩20%吗?他反向写。大家思考一下,他为什么要这么玩呢?为什么不写到100%的时候,写到这100%。然后再反向写呢。如果写到100%,会出现一个什么情况?那是不是要等待将你内存当中所有的数据内存不够了,是不是得一写到磁盘呢?哎,一写到磁盘就是往磁盘的一个文件里面写,这能理解吧?哎,往里面写。那你到把它100%的时候,你要等等它一写完之后,你是不是才能往这个环形缓冲里写啊,那这个效率是不是比较低啊,那现在呢,我是这么写,我存到80%的时候。我开始反向一些了。那如果到80%的反应一写,那也就是说我现在这个时候就已经提前开启了一个线程,从这开始写,那这个期间我要一写了。
07:01
哎,往吃饭里面写。那我如果这个提前写完了,我到这儿的时候,是不是瞬间就还能正常的运行。对吧?啊,那那有的同学说了,那海哥,那你你就写的慢,你这个线程写的慢,写的慢之后,那你这个往这写的时候,你是不是把历史数据给覆盖了,有没有这种可能。有,但是人家底层已经想到这个问题了,他怎么想的,哎,你这个一写的时候,如果说你这面快速的这个增长的数据比他到达这个位置的时候,他还没有一写完,那怎么办,等待。直到等他这个一写完毕之后,你才能写。啊,是这样一套流程啊,所以说它这里面设计的比较巧妙啊。好,那这是到这个地方,那这个再往下,那首先啊,哎,这里面数据进来的时候呢,他上来就把这个数据啊,标记是哪一个分区的了。为啥要标记是哪一个分区的呢?因为未来分区一会进入到REDUCE1,分区二会进入到REDUCE2,他们两个就不在一个文件里面。
08:05
对不对,哎,那我就独立的进行处理就可以了啊。下边呢进行哎,对分区内部的数据进行排序,比如说你一写的时候,我要对你数据进行排序,那这个排是什么排序呢,叫快排。那有没有同学想说,我进来一条数据,我就排一个序,进来一条数据排一个序,是这样的吗?不是啊,记住不是,它是所有的到达80%进行一写前,然后对数据排序。那排序的手段呢,就是快排。那这里面对谁排呢?那对谁排呢?记住它不是对你这里面的这个实实在在这个KV进行排啊,因为你看我这个KV数放在类似这种哎集合或者数组里面吧。我要实实在的去让他们进行一个呃,移位,好动吗?不好动。那我对谁牌呢?我对他这个索引牌。哎,我这个水引索引不记录着它存在什么位置吗?比如说你这零是吧,我这个是零啊十啊,然后20,我记录你这个位置,我只是通过指针的方式,哎,假如说这样啊,举个例子,这是数据KV,数据KV。
09:11
K1K1啊这样,那我这里面有这个k start v start,我让他俩。互换,我让他俩互换,那怎么换,我不改变你这里面的存储位置,我给谁,我给他,比如说我原来它记录的位置是从零到十啊,然后下一个位置呢,是从这个K吧,KV呢,它是从20~30,那怎么办?我就改一下你那个值,我现在把它改成二十三十。那我这个KV呢,变成010。就完事了,我不需要动你最原始的数据,那这个效率呢是最高的。啊,那再往下,呃,那再往下呢,那到达80%的时候啊,它就会将缓形缓冲区里的数据溢写到磁盘上,那一写到磁盘啊,这里面记住它这个两个分区对吧,你这是两个分区,它两个分区一写的时候仍然是一个文件,并不是说拆分成两个文件啊,还是一个文件啊,只不过呢,这个文件呢,这半部分呢,用的是分居一,这半部分用的分居二。
10:11
啊,这个意思啊,那有没有同学有疑问说这个还原缓冲区里面是不是一定只有分区一分区二两个分区呢?不是啊,这个分区呢,是后面是可以进行设置的,进行更改,你设置十个100个都可以。哎,只不过这里面我用两个呀,能代表多数,而且跟你讲原理呢,更清楚一些啊。好。下这里面就假如说这是产生第一个一起文件,第二个一起文件。再来第N个一些文件,那你产生了大量的一些文件,我最终我希望呢,把这个这些数据合并在一起,放到一个地方,把这个放到一起,再放到一个地方,那这个代表的分区一,这个代表的是分区二。对吧,那我希望他们总体都是有序的。那对有已经有序的文件进行排序,用哪种排序算法最快呢?那当然首选规定排序,哎,对已经有序的。
11:04
呃,这个内容进行排序,好,那就是归并排序,保证每一个分区内部的数据是有序的,那分区整体它之间有没有序,没有序,因为我说了,他俩未来都是发送到不同的目的地,排完序也没有意义。好,那现在这个地方它是在哪里啊?是在内存还在什么地方,记住这归并完之后是不是就放在磁盘上了,哎,这是存储在磁盘上啊。那下面呢,这个地方呢,有commander啊commander呢是可以提前进行一些预聚合的啊,啥意思呢?比如说这里面啊,呃,有一个A1A1是这样吗?A11,那那A1A1还记得不?我们传到reduce的时候,之前我们说的传到reduce的时候,Ae,然后ae都传到reduce。那你都传到reduce的时候,你是不是传两次这两个文件传两次,那有没有可能我只传一个AR,我传到reduce的时候是不是一个字符串。那我效率是不是更高一些啊,这个呢,相当于是一个优化的手段啊,当然它有前提条件啊,不是所有的场景它都能进行一个优化啊,后面会给大家详细说啊,先有个印象就行。
12:11
那下一个map test呢,哎,它也是遵循上面这套流程啊,一模一样的,它也会产生对应的分区一分区二。那这个搞定,那这是只是执行了一半,那下面这张图呢,诶是后半截再来看。好,那这是承接上张图啊,Map task1 map test2啊,那这个呢,有一个Mr master,整个程序运行的老大,那这个它呢,就会这个MP master,它会观察说所有的map test任务完成之后,启动相应的reduce task,并告知reduce text。就开始工作了啊开始工作了,那这里面要注意,那是不是所有的map task都结束了才能开启reduce task呢?啊,这个不绝对啊,不绝对,如果你数据量比较小的话,正常情况下呢,确实是等你map task全完事之后启动这对task,但是呢,后面有这种什么推测执行啊,啊就类似于如果我不能不想让等我先合并其中一部分。
13:13
假如说啊,我有100个map test。对吧,那我要都等100个test都完事之后,我再开启的test,有的时候啊,这个效率有点低,那在程序里面是可以设置,假如说我有十个了,我有十个map test,我就先将十个map testag进行一个合并,合并完之后由这十个map test的结果再跟后面90个是吧?啊一一点点合啊是可以这样进行配置的啊,但是通常我们前期先学习的,哎,这个呃,都是先map test结束之后,然后再开启,也就test这样结果。将那radio开启之后。记住,这里面是reduce task主动,从map task对应的分区拉取数据,他是主动的哈,不是map test给他推,一定是reduce主动。
14:02
那他拉取的是自己指定分区的数据,比如说零号分区的,零号分区的,那我只能拉零号分区的。哎,他只能拉一号分区的,一号分区的不能拉,拉混了啊。那再来,那你拉取过来的数据,你看啊,我这个呢,是从ma test1过来的,内部是不是都是有序的,我这个从map text2过来的,内部是不是也是有序的。但是你这个两个放在一起,它是有序的吗。不是,那你还需要进行一个大的排序,将这两个内容排序。形成一个全局排序的文件,排完序之后有什么好处呢?那我未来我要进入到reduce方法。什么样的数据进入的方法是不是相同的?K的内容能够进入到这的方法?对吧,那怎么能让相同的K进入到零的方法呢?你看啊,他这么玩的,他先比你这第一个K是A吧,对吧,它会查下一个是不是A,哎,一看是A,那怎么办?哎,继续继续往下比,你看下一个C是C的话,它就做了这么一件事,直接将这两个传输到reduce。
15:06
为什么他这么做呢?因为前面我已经排好序了,这就是排序的优势啊,我前面排好序了,那我下一个它就一定得是它,不是它的话。那。那就乱序了嘛,对不对,哎,所以说这是这块啊好,那一次呢,读取一株啊读取一组,那把这俩呢,哎扣在一起,那后面其实有一个正常还可以进行一次分组排序,只不过这个分组排序我们在节里面呃,用的比较少了啊,这次课呢,我们就把它删掉了哈。呃,如果想用到的同学呢,可以看那个之前的那个,还读2.7.2那个版本啊,其实意义不太大了。啊,那进入到这个reduce方法里面,嗯,之后那reduce处理完之后,它就要往出写,对吧,那往出写呢,它也不是直接往出写,由谁来完成呢?由它的核心组件output format它往出写。它这里面这个方法里面又有一个record reader,哎,那之前那个叫record啊,Reader这叫writer对吧?啊writer往出写,哎由它往出写接就形成了对应的这个文件啊输出去了,那下一个reduce呢,也是正常的,哎输出出去,这就是整个这个map相关的一个流程,那现在啊,大家就从这个整体上呢,有一个数据流的一个概念就可以了。
16:20
啊,也就是说这个海哥有些个别细节啊,我还没听太懂啊,没关系,因为后面这些细节呢,都会再次给大家详细的去啊,一点点讲,然后包括最后呢,还会带大家去看这个源码。那我们采取的方式呢,就是总分总的方式,先整体上给你一个概念,然后呢,一点点一个一个讲,讲完之后,最后再来一个啊总体的讲解哈,是这样一套流程。
我来说两句