00:00
然后接下来讲一讲程序和数据流的概念,大家其实已经对flink的流失处理的程序有一个概念了,大家可以看到它里边的这个流失处理主要就是分三部分,分哪三部分呢?呃,其实很简单,我们前面在做work count的时候,大家看的也很清楚,是不是就是一上来之后用那个env先去读取一个数据源啊?然后中间是不是各做各种各样的转换操作对吧?也可以map,可以filter,还可以开窗口,可以做聚合对吧?KBYSM什么的啊,各种各样的操作,花式操作啊,这些我们都把它叫做穿梭做转换,最后就是啊要输出什么样的结果对不对?最后再做一个SK,我们是直接把它就print直接输出了,这是不是一种特殊的think方式啊,或者你可以写到文件里面啊,后续明天的时候我们会给大家介绍更多的一些SK算子和SK方式啊,大家就会想到其实flink程序里边主要就是这三部分。
01:03
一个就是source读取数据源,第二个就是中间做各种处理转换操作,对吧?Transform transform transformation,最后是S把这个数据输出啊,那这三部分数据流的这个运行的过程当中,它又是怎么样去运行在我们那个lo上面呢?呃,那大家其实可以看到啊。在这个过程当中,其实这个程序呢,首先会被映射成一个所谓的逻辑数据流,就是data flow,对吧,就我们所说的根据你定义好的source transform,还有这个S,它是不是都是一步一步的这样的任务啊,流式处理的任务对不对?哎,所以我就可以先得到一个data flow,它就会包括这三大部分,那每一个data flow它都应该是一个或者多个source开始,然后一个或者多个thinkk结束,总是这样,然后中间的转换就可以五花八门啊,各式各样,呃,这个data floor呢,就相当于类似于一个所谓的有效无环图,这个大家知道DA对吧?啊,就是这样的一个表达,那大部分情况下,我们在程序当中的那个transform的那个操作啊,就跟就是在在这个我们执行计划里面,大家看这是一个执行计划对不对,在计划里边,我们这一步一步的这个这个转换。
02:28
操作啊,就跟我们这个程序里边的转换算子,就跟我们data flow和这个计划图里边的转换操作,转换算子是一一对应的关系,一般情况都是这样,大家在word count里边就可以看到有map对吧?呃,是不是有那个,呃,大家还记得还有什么,有有south,有think对不对?呃,后后边大家记得还有这个aggregation aggregation可能特别一点,那是我们KBY之后再做丧他是不是把这两个合在一起叫一个aggregation啊啊,对吧,这个大家因为大家也能想到,这是先分区,先分组再再聚合吧,其实就是一个aggregation的过程啊,这就是程序和这个data flow的一个关系,那如果要有了这样一个data flow之后。
03:19
那具体要怎么样去处理,怎么样去执行呢?这可能就涉及到我们最后生成要生成一个执行。那在这个flink里边,它的这个从data flow到执行图的这个过程啊,啊,有时候这个观点啊,可以把它分成四层。什么样的四层呢?就是最外层是stream graph,就是留的这个graph留的图,对吧,或者直接就叫data flow,然后之后呢,根据这个要生成一个job graph生成这个作业图。那这个从graph到这个job graph有什么操作呢?Stream stream graph其实就相当于我们代码对应的那个最初的那个图对吧,就是111个一个算子对应的一一对应的那个最初的data flow,那它生成这个drop gra是谁生成的呢?
04:16
这个大家注意啊,这个是我们的client client,我们的客户端在提交它的时候,就直接已经把它生成了,就做了这个优化了,生成这个job graph,那么这里边做的最重要的一个优化是什么呢?就是把很多个符合节点的这个,呃,就是很多符合条件的这个操作节点,我们的任务节点,把它连接在一起,成为一个大的节点。这大家也已经看到了,我们当时在那个执行计划里面,是不是有很多个任务,其实合在一起当成一个大任务来做的呀?大家有印象吗?对吧,当时我们那个map跟后面那个操作都是合在一起,Filter都合在一起了,Fla map对吧,都合在一起了啊,那它又是为什么会合在一起呢?后面我们再讲啊,这它这里大家只要知道这一步合在一起之后,就会生成这样的一个job graph,然后呢,Job manager就会拿到这个job graph会提交给job manager,对吧,他会把这个job manager。
05:19
生成一个并行化的执行版本。这个执行版本就叫执行图,叫execution graph,这是调度层最核心的一个数据结构,这个图再传给task manager manager就可以干活了。那当然了,最后task manager呢,干活的时候,他还会把这个呃,就是这个s execution gra呢,再做一个调整,就是最后生成一个最终物理上要去做执行的一个一个图,那这个其实并不是一个具体的数据结构了啊,但是一个物理层面上,呃,逻辑意义上。的一个图,大家只要知道这样一个概念就可以了,我们还是看一下这个图吧,把这个还是稍微放大一点,大家看能不能看的清楚。
06:06
好,这样大家应该看的清楚一点,对吧?大家看这四个图的这个操作流程啊,其实就是这样,Stream gra其实是直接在client上生成的,大家看这个生成的过程,其实就是我们一个算子对应这样的一个任务,对不对啊,比方说这里边有个S,这边有个flat map,这里边有一个聚合,这里边有一个SK啊,它就对应的生成这么几个任务的节点。然后接下来他做什么事情呢?啊,做一个优化,就是把有些算子它就合并到一块儿了,对吧?啊,所以大家看这个这个写法是不是大家看着很熟悉啊,我们在当时的那个执行计划里边就看到的就是这样的,对不对,都是很多个任务合在一起的,然后有了这个之后呢,他就可以把它传递给job manager。John manager,他就会把之前的这个drop graph作业图转换成一个执行图,这个执行图是一个什么版本呢?是不是就针对它的这个并行度做了这个并行的调整啊,对吧?这就是最后可以并行执行的一个版本了,比方说这里面Fla map它的并行度是二,那大家看是不是我们前面这个sources就要把这个数据分别发给这两个任务啊,对吧?然后到这里边大家看到如果你要做一些聚合操作的话,这里边是不是涉及到一些重分区的操作啊,大家看这里边就有这个数据的一些交互啊,然后到最后再think输出,这就涉及到这些具体的执行过程了,当然最后的这个物理执行图的话啊,其实这就是已经是在这个task manager上面去运行的东西了,它其实就是说直接对应我们这个执行图里边的每一个具体的物理含义了,啊,这就是我们的这个执行图的含义。
07:52
好,然后再给大家说一下这个并行度。并行度其实前面我们已经给大家说了很多次了,对吧,在很多个地方都给大家强调了这个并行度,并行度呢,我们如果现在再总结一下,它其实可以代表不同的含义。
08:13
我们在说到并行的时候,一般说的是什么呢?大家说的是什么?什么叫并行啊?什么叫变形?啊,有同学可能说就是在同一时间,如果来了大量的数据的话,我可以让他,诶同时这个数据到那边,这个那个数据到这边,对吧?哎,这种是大家可能一般意义上理解的并行啊,这种并行也是我们讨论的最多的,这个可以认为这个叫数据并行。另外在flink里边还可以做什么并行呢?还可以做任务并行,或者说计算并行,对吧?它是一个什么样的概念呢?我们可以让不同的算子,它可以在相同或者不同的数据上去执行。
09:02
它的含义是什么?就是说诶,我这里边假如说一个SW里边执行的对吧,这里边可能是,呃,一个source任务是在读一个最新的数据了,同时另外一个算子里边是不是有可能我执行的并不是SS任务啊,对吧,并不是同时在读另外的一个SS任务,而有可能是在做后面的一个map操作,这是不是相当于就是我同一时间可以在执行不同的步骤里边的这个操作计算啊,哎,所以这个任务也是可以并行的。啊,另外当然还有更高的层级,就是作业也可以并行,就drop也可以并行,大家想是不是这样。呃,我们提交之后,这个slot的资源都是可以共享的,所以在这个过程当中,这个slot可以执行的是我这个当前提交这个drop的任务,另一个slot是不是可以执行另外的其他状况的任务啊啊,其实这些也是可以并行的,所以在link里面它的灵活度其实是非常非常高的,它可以做各种不同程度的并行,我们更多的去呃聊的这个并行呢,一般我们说的就是这个数据并行对不对啊,大家就是同一个任务,同一个计算,然后呃,很多个数据来了之后,我可以呃并行到不同的这个lo上面去把它跑跑起来啊,所以大家会看到啊,一个特定算子的子任务的个数被称之为其并行度啊,这是我们这里面给出来的一个并行度的概念,这其实相当于就是所谓的数据并行了,对吧?呃,一一般情况下,一个stream一个流的并行度,我们按什么来计算呢?
10:39
啊,就是我们前面说的可以认为就是什么,就是它所有算子里边最大的那个并行度,就是它整个零的并行度。啊,比方说这里边大家看一下我们这个这个状态啊,这里做了S,然后做了map,它的这个S的并行度是二,后面是二,对吧,后面也也是二,最后think是一,它的整个流的这个并行度是什么样子呢?对,其实就是二,那它总共需要有几个插槽来做这个任务的执行呢?对,最少只要有两个就可以了,当然你如果要是更多的话,它也可以把更多的那个任务并行开去做执行,对吧?啊,你如果要没有的话,两个也就足够了,而且大家会看到在这个过程当中啊,还有一个细节大家看到了吗?他们中间不同的这个并行度,它它的这个数据是不是会有交互啊,对吧?呃,这个大家看到前面的这个S到map这个数据是不是直接就传过来了。
11:41
而后边这个map到后边的这个K到开窗window的过程当中,它是不是会去做这个重分区啊,对吧?啊,或者说大家理解就有点像我们类似的这种杀手的操作了,对吧?啊,那那这到底又是为什么呢?啊,这个后面我们再给大家再再去说这一部分内容啊,首先我们先看一下,就是在这里我们其实已经知道了这个,呃,就是这个任务执行。
12:07
整个这个过程了,那任务执行的过程当中,它的slot和这个并行度的关系又到底具体又是一个什么样子呢?我们在这个基础上再看一个稍微复杂一点的例子啊。大家看一下这个并行度和这个slot代表了一个什么含义?大家看左边这是一个作业图,这一个job graph,对吧。呃,大家看这个应该认得吧,对吧,这一个drop b,那那么这个作业图它包含了几个算子呢。但这个抽象了啊,这个没有没有特别具体,就直接abcd了,对吧?它有几个,有五个算子,然后下边的这个角标就代表它的并行度,对,所以大家看这其实就相当于是什么呢?呃,它是A和C,是不是相当于就是我们的S算子啊,大家看那它是头对吧?这是一个S算子,那B和D中间转换对吧?那最后的E是不是就是一个think算子啊,所以大家看这个A和AB啊,这个其实只有C和E它俩的并行度是二,其他的都是四,对不对啊,所以大家看一下,如果我们把这样一个job graph转换成并行执行的这个执行图的时候,放在slot里边。
13:23
这个并行度是怎么样的一个体现呢?大家看一下就是右边这个图这样这样的一个情况,因为我们知道整个这个流里边,它最大的并行度的这个算子是不是四啊,所以我们用几个slot就够了,四个就够了,现在我们有两个它manager一个里面有两个slot是不是够用啊,哎,刚好四个,所以大家看他会怎么分配呢。A这个算子SS算子对,那一共就四个lo,它就要求并行64,那是不是就只能是分配了四个里边一边一个啊,然后同样大家会想到B是不是也是一边一个啊,而且A和B之间是不是直通的对吧?直接这个数据就传传给B就可以了,然后接下来大家看C的并行度是二。
14:13
那是不是他就不需要,是不是只要有两个并行的C任务就可以了,大家看他分配就分配到了slot1.1和slot2.1上面,然后接下来到D的时候,它会怎么样呢?D的并行度是四,所以是不是还是每个里面都有啊,而且大家会发现啊B和C的这个数据。是不是相当于每一份数据相当于都要做重新分区啊,对吧,所以D这里面这个操作肯定是这样的一个操作啊,最后对E是不是变成了一个并行度是二的一个输出一个think操作,所以大家看到它变成了这个slot1.2和slot2.2,这里我们就两个D是不是合并到一个E里边去啊,这就是整个最后这个执行的过程啊,所以大家可以看到就是把这个slot调度上,调度到不同的slot上的时候,可以让很多个task就跑在一个。
15:14
同一个task manager里边,甚至可以不同的任务可以跑在同一个slo里边,对吧,很多的资源是可以共享,可以去把这个资源利用率达到最大的啊,但是呢,那当然可以想到,就是说你如果要是把这个太多的。这个任务如果调度到同一个同一个这个slot里边,那是不是就会导致这个效率会低下呀,对吧,那他想要去抢抢占这个,呃,占用的资源就有点有点不够用了,不够分了啊,所以这个时候我们可能还是要注意的啊,那怎么样去处理这样的问题呢?这就是之前给大家提到的,我可以再去给大家设置那个所谓的共享组对不对,Sharing group对吧,可以把它这个东西再再分开,这里边我们默认它是可以放在一起的,我还可以强迫把它分开。
16:06
啊,这是这个并行度在直行图上的一个概念。呃,还有后面一点内容,我们给大家讲完吧,好不好,呃,拖几分钟时间给大家讲完吧,好,接下来还要给还有一个问题大家应该还记得啊,就是前面我们给大家说过,大家看在这个数据传递的过程当中。有些是直通过来的,有些是不是就要做重分区啊,哎,这又是怎么一回事呢?哎,这里边给大家讲一讲,呃,这个并行度和这个数据传输的一种关系。大家会想到,呃,不同的算子可以有不同的并行度,那么算子之间就会有数据的传输,因为你的并行度还会改变嘛,那这个数据肯定是要做传输的啊,他们之间的数据传输的形式可以有两种,一种叫one two one,或者叫fair forwarding啊,就是直通对吧?呃,直接转发这样的一个模式也可以是。
17:06
Redistribu就是重分区啊,重新分配这样的一个模式,具体是哪一种模式,那就要看具体这个算子的种类了,那么one to one这种模式呢,它相当于是什么呢?就是比如说最典型的就是像这个S之后,然后直接map。那map大家会想到它是什么意思啊,是不是就是一个数据来了之后,就直接针对它做一个操作就完事啊,那是不是肯定是一一对应一对一的一个过程啊,所以在这个过程当中,我们的整个的流,它会维持这个数据的分区,以及整个数据的这个在分区当中的顺序,按照顺序一个一个来,对吧?啊,你之前是第几个,现在还是第几个,所以这就意味着前后的两个算子任务,他们产生出来的这个数据啊,它的这个个数和顺序都是完全一样的。
18:00
那大家会看到哪些算子是这样one to one的操作呢?Map filter flat map这些算子都是。大家会看到这个就相当于什么呀,就相当于我们Spark里面讲的窄依赖对吧,那这其实就是窄依赖嘛,这大家一看就知道啊,那同样对应的是不是就有宽依赖啊,那宽依赖就对应我们这里边disributing这个模式,那么它其实就是stream分区会发生改变,就是我们每一个算子,它的子任务可能根据我们选择的这个转换操作,它要发送这个数据到不同的这个分区去,要做重新分区了。那比方说这个KBY,那家大家大家知道这个KBY是什么意思,KBY其实就是分组嘛,对吧,你既然要做分组了,那是不是就是之前啊,有可能你不同不同区的这个数据来源,但是有可能它是同一个K,我是不是要分到一个区里面去啊,那你之前是呃,同一个区的数据,根据不同的T就就要把它分开了,对吧?所以它其实是基于哈希code去做了一个冲分区的。
19:07
那同样这个key by,这是一个重分区的操作,还有什么操作呢?还有这个broadcast广播,还有这个reb啊,他们都会随机重新分区啊,那么大家可以认为这个过程就类似于那个杀走的过程,对吧?啊,所以大家结合起来看就知道是怎么回事儿,那这里边我们还留了一个小问题呢,留了一个什么问题?就是我们前面讲它这这些东西不是说有这样两种方式嘛,弯凸啊窄依赖对吧,或者说重分区这样的一个宽依赖,我们前面还讲过它这个生成那个就是job graph的时候,作业图的时候不是做了一个优化,可以把不同的任务合并到一起吗。那这个什么样的任务能合并到一起做这个优化呢?哎,这里边就给大家把这个再做一个啊最后的描述,这就是所谓的operator trip任务链这样的一个东西,这是flink里边的一种优化技术啊,它其实就是说在特定的条件下可以减少本地通信的开销,为什么大家会想到我把不同的任务直接合到一块儿了,那是不是合成一个大任务了,是不是就没有那个互相之间通信传递数据的开销了呀?啊就是我相当于就变成不用去传递数据,不用做序列化了,直接就变成一个本地调用了,那这个就很很简单,那什么样的情况可以满足直接合并起来,多个任务合并成一个任务链呢?它有两个要求。
20:36
一个是必须是相同并行度,另外还有一个就必须是one toone的操作啊,这个大家可以理解吗?啊,你不能做重复分区呀,你如果要做重分区,那肯定我这个就没办法合并了啊,另外就是你不能并行度变了呀,并行度变了,它那个分区是不是就发生变化了,你当然就不能直接合并了,一定要做那个数据的重新发送对吧?转发你不能直通,哎,所以大家注意这里边有两个条件,并行度相同,而且是one two one操作缺一不可,符合这种条件的,我们在啊生成drop graph的那一步里边就做一个优化,把它合成一个任务链啊,这样来做一个处理啊,这就是我们在这个整个这个运行时架构里边涉及到的一些概念。
21:28
啊,那大家看这个怎么样去合成这个任务链呢?其实非常简单,这里边S的任并行度是二,前面的这个算子KY之后聚合的并行度也是二,对吧,而且它们之间是。他们之间是不是直通这个one图案的这种数据传输啊,所以在这里边我们就直接把它俩合成了一个任务链,那大家看你这里边是并行度12,我前面这个flag那不也并行度是二啊,为什么他俩就不能合呢?对,因为这里面皮是不是重分区了啊,这个就解决了我们当时看到那个呃,Web UI里边大家看到那个执行计划的那个问题了,对不对,为什么总是在那个aggregation那里就给它断开了呢?就是因为做了重分区,呃,所以它就不能合成任务链了,而前面如果它是one to one,而且并行度相同的话,就可以合在一起,就这就是我们这部分内容好。
我来说两句