00:00
接下来我们给大家讲一下这个叫for的算子啊,嗯,这个算子呢,之前有的同学就问过我了,说老师你看咱们写代码的时候,总是先写一个collect,再写个for each,那其实啊,我们点击RDD之后,它就直接出现一个for each,那这个算子方法我们为什么不去用一下呢?老师,那你是不是写错了呀?啊,或者是没有注意到呢?其实你们想多了,那你们老师我怎么可能没有想到对不对,所以啊,我千方百计的,我的目的就很简单,就是为了绕过这个for算子啊,我们才会一直在使用那个collect算子啊,原因在哪?是因为这个for each算子啊,它有一些特殊的现象,它的一些原理性的东西我们还没有讲。啊,那这样的话,如果我们直接使用它的话,担心大家会有疑问啊,所以啊,我们当时是一直去绕过去的,但是我们接下来咱们就要讲它了,那接下来呢,我们先看一看现象,咱们再描述它的一些原理性的东西啊来拷贝。
01:00
拷贝以后呢,我们写上一个我们的零六啊,然后呢,写上它好点击OK,咱们放过来。好了,放过来以后把这些东西我们都去掉,去掉以后呢,我们写上SC点啊,我们叫make RD,咱们的LIST1234好吧,然后呢,我们写上啊,咱们的这个叫做RDD,很简单啊,同学们看我直接写RDD,点我们叫collect,然后呢,点我们叫做什么呢?咱们叫做fora it,然后我们的print。好,但是呢,我在中间呀,我加上一个打印语句,我们写上叫星啊,咱们叫做星,好,接下来我们写上RDD点我们叫做for it,然后直接来我们的print,好了,大家有没有发现好像少了一个collect吧,那行,那这个时候呢,我们来给大家看一看啊,来咱们运行运行以后看一看它两个不同的循环的一个区别啊,两个都叫辅助一次,那么区别在哪呢?要看看我们的执行结果了啊同学们。
02:06
好了,同学们,结果出来了,你们能看懂它的区别吗?能不能看懂?我相信能看懂吗?为什么?因为咱们的这个星号之前是先采集再去循环,所以1234这个咱们其实是讲过的,我们的collect算子呢,它会将我们的数据以分区为单位来采集,回到driver端,那就意味着会按照顺序一二这是前面一个分区,三和四是在另外一个分区,它会后采集,对不对?所以啊,在当前情况下,它是1234。但是你要记住啊,同学们,咱们的FOR1词它就没有顺序的概念了,所以也就意味着在咱们执行的过程当中,它并不是按照顺序把数据采集过来的,其实也不叫采集了,因为for意思就是循环嘛,那么你的这个print其实它是在我们的execu端去执行打印操作,而咱们这个的print呢,它是在咱们driver端的内存中打印的啊,所以把这个现象咱们说一下啊,咱们的这个for it啊,这里的for it呢,它其实它是什么?是我们driver端啊,咱们的driver。
03:19
啊,咱们driver端,咱们叫内存集合的循环便利方法,咱们的循环便利方法诶是这样的,而我们的下面的这个for呢,它有点不太一样,为什么呢?因为下面的这个for each啊,它其实嗯,它其实啊来它其实是我们的execuor端啊,Execuor端啊,我们叫内存数据的什么一个我们的打印,哎就这意思。所以这是两个不同的概念,一个是在driver端,那么driver端是要把数据拉取回来,我们来循环遍历的,而这个其实是分布式打印,为什么?因为它会把每个数据发给不同的什么,我们的exor端是这个概念啊,所以啊,咱们画个图来理解一下,同学们啊,咱们来,呃,回到哪呢?就还是在这儿吧,嗯,咱们在这个下面吧,啊来。
04:13
嗯,咱们就别新建一个我们的目录了啊,直接建在一个文件上去建立,那么比方说我们的第一个啊,咱们第一个来拿过来,我们第一个是这样的啊,咱们的这个driver啊,咱们的这个咱们叫driver好了,然后呢,接下来咱们给他一个红色啊,给他一个红色来表示一下,嗯,好,然后呢,再来我们的executor放这边,嗯。好,我们的executor放过来,以后同志看啊,来,我们把这个呢给它放过来,然后呢,我们干什么了呢?来,我们这样啊,咱们这样来。呃,我们在这里啊,同学们看啊,咱们假设啊,咱们这里有数据了,那有两个分区啊,咱们这里有两个分区,嗯,好,那两个分区呢,我放到这里啊,那这两个分区啊,咱们现在里面有数据啊,它里面有数据,它里面有数据的时候,比方说哎,我们写个一是吧,然后写个二,哎,咱们写个二好了。
05:09
这么写完以后再来我们拷贝复制到这边来,那这个呢是我们的三,嗯,这个呢是我们的这个四,哎就是它了啊好了,那我们现在咱们举个例子啊,比方说我的一和二干嘛呢?诶发送给我们的exor,发给他来执行对吧?诶发给他来执行了好。然后呢,我放到这边,嗯,行,然后呢,我们再来啊,咱们再来把这个放过来,咱们的三和四呢,发给他执行好,那这个时候啊,他们这边记住了,同学们,我们现在发过去了,你发过去以后,你是不是要把它采集回来,它的结果采集回来吧,那我们这里没有做任何的操作,他就直接采集回来了,对不对,所以啊,他就往回返啊,他就往回返,他往回返的时候,其实你会发现每个ex都会往回返吧啊,他都会往回返啊,都会往回返,所以这边呢,它也会往回返啊,往回返,但是你要记住啊,他往回返的时候,它会按照它的分区的顺序来怎么采集数据,你可以理解为是把我们的这个,诶前面的这个分区的数据呢,先给它拉取回来啊,放到我们数录当中,然后再把这个呢,数据采集回来,放到我们数录当中,这样的话,它循环打印是在哪儿打印呢?它的循环打印呢,其实是在我们的这个。
06:29
杯子打印啊来。它是在咱们这个地方,它就实现的这个pro的操作,所以呢,它会按照我们的顺序1234就把它打印出来了,所以啊,它的原理呢,是这么个原理,对不对,所以它是有序的啊,它是有顺序的,但是我们刚才的那个操作有点不太一样,来复制一下,复制以后大家看啊,来往这边放,你往这边放以后,那我们这里大家看一下,诶我们的print,记住,由于啊,你的这个for它是一个循环操作,而且是一个分布式循环操作,所以这个print功能其实不是在driver端执行的,而是在我们的ex执行的,这个能不能明白。
07:10
所以啊,同学们看这个图,我们的print其实啊,它是在这儿执行的,哎,在这执行的。为什么呢?因为我们就是要在不同的节点上去打印,对不对?诶,我的数据发过去,一和二发过去,三和四发过去,我们不拉取回来了,你不用拉取回来,你只要发过去就可以了,发过去一和二就打印,三和四就打印吧,对不对?同学们就是这样,但是你要记住同学们,谁先打印谁后打印,这个事儿能确定得了吗?分布式执行,如果资源足够的情况下,是不是并行计算,那么谁先执行谁后执行其实是不确定的啊,所以呢,我们就会发现,我们之前这个是有顺序的,但这个根本就看不到顺序,对不对?这就是它的区别,我们之前为什么一直就没有给大家去演示这个功能,就是因为担心啊,大家会有疑问说老师为什么是乱序的呢?诶,当时如果去讲的话,大家可能啊会觉得有点难,那我们现在就要说一下,它就涉及到一个概念,什么概念呢?就是我们的计算逻辑是在哪一个地方执行的啊,所以我们在这里说一下来。
08:17
这地方也正好要回过头来说一个我们之前非常重要的概念,就是什么叫算子啊,什么叫算子,大家还记得吗?我们说了所谓的算子其实就是叫operator,还记得吗?就叫operator啊,这个我们称之为叫操作,对不对?那问题就来了呀,我们为什么叫做算子呢?主要的原因就是因为什么?主要的原因它就是因为我们RDD的方法,记住啊,哎,我们为什么要把这个叫算子,就是RDD的方法,它和史GALA集合对象的方法,集合对象的方法它不一样。他哪不一样了呢?诶,我们集合啊,对象的方法,它都是在我们同一个节点的内存中完成的,内存中啊,咱们完成的,比方说什么循环便利啊,什么聚合呀,这些东西它都会依托于什么,我们的同一块内存对不对,但是我们RDD的方法它就不一样啊,RD的方法。
09:23
它是可以将我们的计算逻辑发送到啊,我们的什么咱们的exeutor啊,端执行的,或者说叫分布式节点也行啊,咱们来写上叫分布式节点执行的,所以这个概念明显就发生了改变,就意味着这个地方的print其实是在driver的内存中,而这个是在已Q当中的内存中完成的,那你说能一样吗?那肯定不一样,对不对?所以为了区分咱们的该集合的方法和RDD的方法,我们才把RDD的方法称之为叫算子,所以叫算子的目的是为了进行区分,不要混了啊,所以我们这里也说一下来,为了区分啊,我们的不同的处理效果啊,所以将我们的RDD的那个方法称之为叫算子,哎,这是为了区分,那么叫算子的目的就是为了告诉你,告你什么呢?我们的RD。
10:24
D的方法啊,它的比方说for it方法,它外部啊,外部的我们的操作啊,就是方法外部的操作,它都是在我们driver端执行的。啊,而我们方法内部的逻辑代码啊,咱们叫做内部的逻辑代码,它是在我们的exe。端啊,我们执行的,所以把这个搞清楚了,那这一块我觉得就行了啊,就是我们重点的就告诉你这个逻辑,它是在哪个地方执行,你这个肯定是在driver,而你的这个一定是在E老师,那我这个打印是在哪啊,要记住这句话。
11:07
这个RDD的方法,这是不是RDD方法啊,这个方法的外部的操作就是在它之外的,这个操作一定是在driver端执行的,但是它里面的这个逻辑操作就应该是在excu端执行的,所以啊,咱们这个图形当中的driver和这个你们要区分好,一个是在我们的driver中print,一个是在我们的ex端print,这是不一样的啊,千万记住千万记住千万记住啊,同学们。
我来说两句