00:00
好,接下来呢,我们给大家讲一下这个排序啊呃,讲排序之前呢,我们先看一下这个Mars这个流程,还记不记得这里面的一些过程啊。当时啊,咱们说这个欢迎往城区,哎,我快速把前面这个过了哈。在还原缓冲区溢血之前,是不是要对这个数据进行一个快排呀?还记得吗,这个地方。啊,这个快盘,然后呢,它会产生多次的一写文件。那多次的一些文件,我们需要对它再进行一次规定啊,也就是说在整个map map6当中,Map阶段它执行了两次排序,分别是在环形缓冲区溢写之前进行了一次快排,那这里面是对谁排?还记得吧,对key的索引排序按照什么顺序排,按照字典顺序排,OK,那对一写文件呢,我们又再次进行了一次诶末结合并操作。我把这里面啊,截张图吧。
01:00
我截张图哈,后面以备待用。从这截就可以了。好,这是其中一个定图,然后接下来呢,我们来看一下这个radio阶段我们进行了几次排序。Reduce阶段是map阶段结束之后,Reduce呢主动的去拉取对应的数据,那他拉取自己分区的数据过来之后,他需要对拉取过来的数据进行一次归并排序。对吧,哎,归并排序。OK,那么规定排完序之后,如果说他想控制这个后续,那也说对这个key里面的内容再进行一个排序,其实也是可以的,那这块呢,是可以进行一次叫分组排序,但是啊啊,由于我们二六程序写的已经比较少了啊,所以说这个复杂的这种分组排序啊功能啊,嗯,这次呢,我们也把它删掉了啊,因为在开发中用的非常少啊。行,那你就记住一次就行了,记住有一次归并,这是系统自带的,那当然了,我们也可以进行自定义啊。
02:03
OK,那这个呢,我再定一张图。拿过来。啊,也就是说现在我们总结完之后啊,在这个map阶段进行了两次快排和归并,在review阶段进行了一次归并。好,那接下来我们就来全力以赴研究一下对应的这个排序。首先这句话排序呢,是MAP6的框架当中非常重要的一个操作之一,可以这么说啊,分区和排序。呃,在面试啊,还是开发的时候,如果你用到你的概率啊,会非常非常高啊。再往下,下面呢,这句话看一下叫map reduce map task和reduce task均会对数据按照K进行排序。该操作呢,属于hi默认行为。这个很重要哈,也就是说,呃,不管你是map test还是test,它的key必须可以进行排序。如果不进不能够支持排序的话,那么还多这框架直接报错了。
03:03
比如说海哥,我就想这个不排序啊,行不行不行啊,除非你自己再写个框架啊,这个要注意啊,任何应用程序均会被排序,不管逻辑上是否需要,你说不管你要不要啊,反正我就给你排了,那大家思考一下,为什么一定要对它进行排序呢?有没有想过?你说这,这不是给自己找麻烦呢吗?啊,原因在这啊,如果你前面这个数据不排序的话。你看到这块。咱们reduce reduce这块。呃,最终是把相同key的内容是不是进入到里面。如果你在前面不经过一系列的这个排序操作,那你到这儿,那就有可能是A,下一个是C,再来一个呢是E,然后又来一个A,又来一个C。那你每次将相同的key进入到reduce里面的时候。你是不是得一个一个去判断它是否是相同的K。那你觉得效率高吗?那反观我们现在,我们现在呢是。
04:05
把相同的K数已经排好序放在一起了。那我只需要跟下一个去比较,跟我当前的K是否一样。如果一样,那就是相同K不一样,直接就把这一组拿走,进入道里就行。是不是效率更高一些?啊,这个呢,有的时候面试官还真问说我们这个,呃,MA60当中这个key为什么一定要排序,原因就在这儿,为了提高箱的效率啊。下面说诶默认排序啊,是按照质点排序啊,而且呢,该排序的方法呢,是快排,这个说的是map test阶段这块。对吧,哎,按照这个ABC啊D这种方式进行排序,排序手段呢是快排,那对呢,是对K的索引进行排序。好,这是第一个概念了解,那接下来呢,再来看一下文字描述啊。这个。的,对于map task,它会将处理的结果呀,暂时放放到这个环形缓冲区当中,当环形缓冲区使用率达到一定阀之后,再对环形缓冲区的数据进行一个快排,那这个呢,大家一定要注意哈比就说不是你进来一条数据,我就一定对你先排序。
05:16
它是啊,到达一定阀值之后,要往磁盘上溢写之前进行一次排序啊,那这个排序的过程呢,是在内存当中完成的。OK吧,这个要理解。呃,然后一些,呃,而当数据处理完毕之后,他对磁盘上的所有文件再进行一次归并,那所说的归并呢,是这块,比如说这里面产生了大量一些文件。那我们需要对一写的文件按照指定的分区进行合并汇总。合并汇总。这就是map阶段,两次排序说的就是这个事儿,那接下来我们看一下radio阶段。对于radio,它从每个map task远程拷贝相应的数据,这个注意啊,是远程拷贝,或者你说拉取也可以,不是这个map主动来推,如果文件大小超过一定阀值,则一写到磁盘,否则存储在内存当中,啥意思呢?你从远程拉过来的数据啊,我先放到内存,内存不够的情况下,我会放到磁盘上。
06:17
这很显然的道理啊,放到内存计算速度快呀,你直接放到磁盘那速度多慢呢?但是有的时候这个嗯,想法很好,现实很怪,我的内存啊非常少,那存不下了怎么办?那存不下只能存在内存呗,啊,存在这个磁盘呗,嗯,那个道理是一样的啊。将如果磁盘上的文件呃达到一定阀值,则进行一次归并,生成一个更大的一个文件啊,如果内存中文件大小或者数目超过一定阀值,则会进行一次合并,将它一写到磁盘,啥意思呢?你说啊,最终啊,其实是不管你在内存当中的数据还是在磁盘当中的数据,我都要进行一次统一的。规定啊,规定排序,为啥要统一规定排序啊,啊,还是那道理,因为我们是将相同的key要传输到reduce方法里面去,那你只有统一的全都排好序,那你这个效率才能是最高的,否则的话,你得每一次这个获取K都要便利所有,那你如果这是11个K呢?
07:14
每次要遍历11遍对不对?嗯,这个得不偿失啊,好,这是呃,Map text和TEXT3次排序一定要记住,那当然如果你说还能还有一个分组啊,那有的面试官啊认这个分组啊,有的不认啊,为什么说认呢?嗯,认呢是因为它是一个自定义的,而且也能实现排序,那不认的道理呢,是因为它不是系统这个默认给你实现的这个排序功能啊,默认的排序功能呢,就是在map阶段,嗯,快排归并,Radio阶段归并。对吧,这个怎么说的都有啊。嗯,反正不管怎么说,你知道有这个事儿就可以了。下面我们来看另一个概念,叫。部分排序什么叫部分排序呢?Webs可以根据输入的记录的键对数据进行排序啊,都是key呗,哎,保证输出的每个文件内部有序。
08:08
那还记得咱们那个手机号吗?手机号1361个分区,137138139,然后其他。对吧,它的什么含义呢?它要求啊,你每输出的一个文件内部游戏,诶你这一个文件有游戏就行了,你比如136的手机号按照什么什么顺序金牌就可以,那另一个呢,是137,哎你内部按照比如说按照总总流量嘛,啊来一个倒叙,我们后面一个案例就这样要138啊倒序。哎,这叫部分排序。那再来一个。全排序。什么叫全排序呢?说最终输出结果只有一个文件且内部有序,那就像我们第一次统计word的时候,我所有的单词都会进入到这一个PART0这个文件里面。那在这个文件内部,我要求所有内容有序。那记住哈,这种情况下,在生产环境下呢,一定是要慎用的,为什么要慎用啊,在生产环境下这个数据量会非常非常大。
09:05
可能会有十几个T。对吧,啊,甚至十几个PB。都有可能,如果你把所有的数据都聚合到一个reduce里面,那你觉得reduce能处理的了吗?对吧?哎,所以说在企业里面啊,进行全排序的可能性其实不太大啊,通常是怎么排序呢?就按照分区内排序,比如说上面这个排序会用的比较多。比如说某一个地区,哎,这个销售额前十的。对吧,比如说东北地区销售前十,呃,华北地区销售前十一般呢,像这个呃,双11啊,或者618的时候,对吧?啊,都有这种排行榜啊,或者说这个北京人呃,这个喜欢的十种食物,最受欢迎的十种食物啊,什么广东最受欢迎的十种食物诶等等这种这个例子比较多哈,他不会说啊,这个全国所有人。他的一个啊,销售情况咔列一个大单,这个没有意义,那所有人数据都进入到一个大榜单里面,那完了。
10:01
嗯,而且你也不利于你也没你也没法看呢,你光看那个十三亿十四亿人。对吧,那你得看到啥时候去,得看好几年,意义不大啊。那接下来往下看,还有一个呢,叫辅助排序啊,那所说的这个辅助排序排序啊,就是我们说的这个radio阶段这个地方啊,就分组排序啊,那现在呢,我们已经把它删掉啊,知道有这么个事儿就行了,也就是说呢,我们可以把进入到这个radio阶段这个key啊再重新。进行按照我们用户的要求再进行一个排序啊。用的比较少。200斤。在自定义排序过程排序过程当中,如果compare中判断条件为两个的话,就叫二排序。啥意思呢?我们马上要自定义这个排序。啊,马上制定排序,那要重写这个readable compare包接口啊,重写里面对应的这个compare to方法compare to啊它其实是Java里面的,对吧?啊Java的一个接口啊,可以是重写的,那重写之后,那我们按照这个排序的原则,比如说我先按首期总流量。
11:05
排序,那如果总流量相同的话,我得按上行流量哎来一个倒叙,然后再下行流量再倒叙。什么意思?比如说总流量都是240。那怎么办?那我想我得按照第二个元素参与进行一个排序啊,第二个元素,比如说他是呃,第一个人是120,那第二个人呢是300。那我来个倒叙的话,那就把300这个拿到上面。啊是这一意思,就是说参与的元素啊,啊个数有多少啊,二次排序,那二次排序呢,其实每家公司的叫法也不太一样啊,有的像我刚才说的这种,那还有呢,是这个呃,自定义排序,它也叫二次排序。叫法不一样啊,这个没关系啊,只要他能解决我们对应的这个用户的需求就可以,我们后面会有案例呢,专门来练习这个分类啊。呃,下面呢,就是如果说我们要自定义排序的话。那我们的步骤是什么?怎么办呢?诶。很简单啊,比如说我们对B对象,嗯,作为可以进行传输,我们那个罗B还记得吧,手机号那个B。
12:05
我想让它放在key里面进行传输。那他必须得支持排序,因为咱已经说了,Hido框架呢是默认要求K必须得能排序,不管你在业务上需要还是不需要。你只要不能排序,那直接就报错了,你要重把这个B对象直接放到key里面,而且呢,还没有重写这个,呃,Right包包接口。啊,那那就完蛋了啊,好,那实验的步骤啊,就是要实现red包compare接口,哎,重写里面的compare to方法。那咱们之前序列化的时候,还记得我们重启的是哪个接口不?还记得吗?序列化的时候,我们实现的是不是right啊,你看一下。打开。Shift啊,双击shift啊。卡住了,稍等包回来之后,我们嗯收一下对吧?哎,这是我们呃,Right包接口,那现在呢,这里面你看一下啊,这里面有没有compare出方法啊,没有,那得用哪用谁呢啊继续shift shift。
13:04
Readable comparable。你看接口它是。这个是继承了对吧?哎,继承了这个redable,还继承了这个啊compareable接口对吧?哎,那你不能说你咱们自己写这个哈,比如说咱自己写一个类啊,这个继承了red包啊,也有继承了这个compare包啊,这样其实呢,它这个语法上校验还是比较严格的啊,它不允许这样,那怎么办呢?哎,你只能继承它。啊,或者实现实现的接口对吧,哎,把这俩就都包含了哈。这是它的一个语法要求啊。那回到这儿。先看。这很简单吧,哎,然后呢,那这里面嗯,就得重写它的这个compare to方法吧,哎,Compare to方法是属于谁的。是不是属于他的,你看。接口嘛,接口里面需要有一个compare方法,哎,重启它就可以。
14:04
那在这里面我们就可以根据我们自己的用户业务逻辑进行一个编写啊,那后面呢,我马上就开始做这个案例。
我来说两句