00:00
我们已经讲到了关于flink里边slot和并行度的关系,现在我们就明确的提出概念了,Slot大家可以认为就是呃,一块独立内存的分配对吧?就是task manage上面资源执行任务的固固定大小的一个资源,一个这样的资源的子集,我们说它主要就是一个内存的隔离啊,那呃,具体到这个并行度的话,那它其实是一个动态的概念,我们说slot的数量是task manager并行执行任务的一个静态能力,那至于这个能力要不要用起来,那就涉及到你动态的这个并行度到底设多少对吧?这个并行度一设置之后,它代表的是当前每一个任务到底有几个并行的子任务,然后给它分配slot就可以了,对吧?啊,那大家就会发现我们能够执行起来任务的话,那这个要求就肯定是你动态的那个并行度想要占用的slot,它,它代表这个就是并行的。
01:00
的任务的这个个数,真正运行时候并行任务的个数,它必须要小于我们的slot总数,能提供可用的slot总数,就是动态的占用,要占用的资源必须小于我们静态的能够提供的资源,对吧?啊,你必须能力得得包含它嘛,这是大家很容易能想到的一点,但是我们具体来看的话,就会想到,那每一个任务是怎么样分配到slot上去,呃,上面去的呢?我们前面不是提了第二个问题,问大家的是说所有的这些任务到底它应该占用多少资源呢?占用多少slot呢?哎,这就涉及到一个,呃,每一个任务分配到每个slot,分配到多少slot上这样的一个问题了。那对于当前的这个问题而言,大家看到啊,前面我们给的这个事例就这个例子啊。前面的三步操作,Source map,还有这个开窗,这些并行度都是二,所以我们会发现这个每一个它都应该有对应的两个任务,对不对?然后后边呢?呃,这个think并行度是一,它应该有一个任务,所以大家看它如果分别来看的话,我们这里边是把它就是变成了五个任务,哎,有同学说你这里边如果看的话,这不应该是七个任务吗?啊,这涉及到另外一个问题,因为前面我们在给大家看这个执行计划图的时候,大家也看到了有一些任务可以合并,对吧?啊,这个我们放到后面再说,现在我们就已经把它合并了,比方说前面这个SS和map已经合在一起了,那现在大家看啊,按照他俩这个算一个任务来算的话,现在其实就有五个任务,那这五个任务是不是就要占用五个slot呢?
02:43
啊,但当然可以这么想对吧,我每一个任务就占用独享一个自己的这个内存空间嘛,占用独立占用一个slot,它是一个单独的线程去执行,那这样的话,这是不是就要占用五个slot呀,那这个是没有问题的。但是大家想一想,是不是当前我们的这样一段程序,你就必须用。
03:03
至少要有五个lo才能把它跑起来呢啊,大家感兴趣的话,下去之后大家可以试一试啊,就是我们说的,你假如说并行度给二,最后一个这个think并行就给一啊,就是我们说的那个,呃,按我们的那个代码的话,最后应该是六个任务对吧?那最后是必须要有六个slot这样才能跑起来吗?其实不是的。其实最后我们测试的话,大家会发现最后的结果是只要有两个slot就能跑起来了。它最后的效果是什么呢?其实大家看是这样的一个效果。啊,这里边当然这个并行度就更高了啊,跟刚才的那个效果又不太一样,大家看当前我们的并行度就调整起了,上面所有这个source map,还有这个window开窗的操作,并行度变成了一字排开,大家看六对吧,变成六,然后占满了我们这六个slot,那大家可能想到,那那你要这么说的话,总共我们现在有13个任务啊。
04:00
那是需要13个slot才能把它跑起来吗?不是的,现在的六个slot已经能把它跑起来了。那他跑起来的这个任务分配的样子是什么样的呢?哎,我们看到它是每一个并行的,当前的这个source map啊,这是一个任务,每一个并行的任务单独占占据一个slot,但是呢,前后发生的,因为大家知道我们这个数据流里边,它本身是有前后发生的任务的,对吧?那前后发生的任务大家想对于同一个数据来讲,你说它有可能并行吗?有可能当前我来了一个数据,呃,来,来了一个这个,呃,A,这个word,对吧,我要去做这个count,那你说他在读进来数据做source的时候,有可能同时在做map吗?有可能同时在开窗做统计吗?肯定不行,对吧,肯定得一步一步来呀,对于每一个数据而言。这里边我们所有的任务,它的先后顺序是不能变的,是不可能去并行处理的,我们这里边说的并行主要指的是什么呢?主要指的是数据并行,就是说不同的数据来了之后,我同时来了一个A,来了一个B,我可以给它分配到,同时分配到两个不同的SS任务上去,然后同时把它们读进来,对吧?啊,那这样的话,我们处理的效率就高了嘛,呃,这个并行能力就强了,这是我们所说的并行。
05:24
而如果说是这个前后发生的任务的话,我们会发现同一个任务,它它同一时间段同一个数据啊,同一时间段它其实只能执行一个任务。所以在这里边我们允许怎么样呢?允许把前后发生的不同任务。让它放在一个slot里面,也就是允许不同的子任务共享slot。啊,那当然下面这一个,呃,这一句话可能说的稍微有一点绕,拗口啊,有点绕,那大家主要理解就是理解什么呢?就是如果是同一个任务,同一步操作的并行的子任务的话,大家想我现在要让数据并行,那是不是你不能放在一个lo里边,对吧?你如果资源还共享的话,这个就没意义了嘛,它相当于还是还是一个子任务嘛。
06:15
所以他们必须要占据不同的slot,把它一字排开,但是对于先后发生的不同任务的子任务,我们这里边呢,允许他们做这个slot共享。那这样的好处是什么呢?呃,一方面大家可能想到啊,这个好处就是说首先没有坏处对吧,没有影响,因为我们并行执行的时候,我只关心当前的,诶这个数据,我不同的数据来了之后,可以同时执行这个source map,可以同时执行后面这个开窗统计对吧?呃,这里边你你可以走不同的这个slot里边的这个任务嘛,去做操作就完了,那至于说前后发生的这个任务呢?其实我并不关心对吧,你来了一个,来了一个A,来了一个B,它其实就是执行到哪一步,我直接去执行,执行完了之后,执行下一步就完事了。
07:05
就是我可以是在当前slot里边直接去执行下一步,对吧,而且这个还更方便大家看到有没有对吧,就是放在同一个slot里边的话,它的一个效果是什么呢?就是一个slot就可以保存整个作业的所谓的这个管道pipeline,好,这里边就是提出了,就是我们所谓的这个pipeline的这个概念,大家还记得在之前我们的那个配置文件里边讲到。呃,我们之前在这个配置文件里边yama文件啊,康康下边的这个flink com的ya某,大家还记得讲到这个上面我们提到啊。大家看到这一句啊,我们看到这个task manager的number of tasklos的时候,它上面有一句注释,说每一个slot可以运行一个并行的管道,那这个管道指的是什么呢?哎,但是这管道水管嘛,对吧,就是顺着那是不是相当于从前到后的水流都可以从它流过,其实就是相当于什么,就是保留了我们整个处理流程的每一步操作,对吧?
08:15
啊,就是像我们这里边定义的,你从前面的source map,到后边的开窗,到后边的S,所有的操作可以在同一个slot里边直接完成。那那它的好处就是,假如说你现在不需要做沙啊,不需要做这个,呃,这个数据的重新分配和传输转换的话,那是不是相当于我就在本地就就直接把它都调调用完了。根本不涉及到数据的这个来回传输和杀戮的过程了,对吧,那这个就特别特别的简单。然后另外还有一个好处是,我既然一个slot保存了整个作业运行的管道,那是不是别的即使挂了别的task manager挂了也不影响我整个处理的流程啊,啊对吧,因为在这里边,因为think是并行度只有一,所以大家看到这个完整的管道保存的话,现在只有一个,第一个这个lo是完整保存的,对吧?那如果说你这个SK的并行度你也调上来的话,那是不是就可以有多个slot都保存完整的管道,那那最后的效果就是说,即使有一些挂了,那剩下的那个,呃,只要我们这个是呃,没有没有全挂,对吧,它还可以正常读取,正常运行,后面是完全可以去去去做这个,呃,保留我们当前的这个执行的状态。
09:27
啊,这就是所谓的保存作业,整个管道的一个啊,这样的一个意义。那另外它还有一个额外的好处,呃,那大家知道,就是说,呃,对于这个不同的任务而言,你比方说像这个source map,还有这个kba,呃呃,就不不是K啊,Kba我们说不属于这个操作任务啊,它是一个数据传输,就后边K之后的这个开窗计算统计,那我们会发现不同的任务,它其实啊是有不同的复杂程度的,对吧?它对CPU的这个占用,它的这个操作的复杂程度其实是不同的,有一些可能是CPU密集型的,比方说我们做这个开窗统计,有可能里面就要做非常复杂的计算,这个可能对CPU的占用会非常非常高,对吧,它是一个CPU密集型的这样的一个操作,而对于这个source map而言,它可能就比较简单啊,就是我们只是读个数进来嘛,对吧,然后map只是做做一个非常简单的对应转换嘛,啊,这这个对于CPU而言可能一瞬间就过去了。
10:30
那大家想一想,你假如说用之前的这种方法,每一个任务都给他单独的分配一个的话,那会出现什么情况?那是不是相当于绝大多数情况,我们都是在等这个window这里边操作,他他一直在那里做做做,呃,这个开窗统计,他一直占着CPU,然后运行不完,对吧?啊,它这个非常慢,一直在这里,在这里跑,在这里等,而我们的这个source map呢,就会出现什么呢?诶我很快就处理完了,我在不停的读数,不停的读数,把很多这个新的数就全读进来了,做完这个map转换了,然后就都堆在这里,然后没有办法执行,下一步就会出现这种情况,对吧?哎,这就是我们说的这个忙的忙死,闲的闲死,然后你就出现这个数据堆积,这不就产生被压了吗?啊所以为了避免这种情况出现,让我们的资源能够更加平均的利用开来。
11:23
那一个方法就是怎么样。也就是我们的忙闲做个搭配嘛,对吧,大家大家这个男女搭配干活不累啊,这这就是你这个CPU占用比较高的任务,和这个比较相对来讲对CPU占用不太高的任务放在一起共享slot前后发生的这个啊呃放在一起的话,那就会导致,呃,就是你这里边假如说你这个source map很快做完了,诶没关系啊,你可以处理别的数据,处理完之后的那个,接下来的那个开窗聚合的统计的那个操作啊,诶接下来就又利用起来了,对吧,你也不要着急,马上就读新的数据,这样就不会造成资源的浪费,资源的利用率就会更高,也不会造成数据积压啊,这就是这样一个slot共享的一个好处啊,那这里边要给大家再强调的一点,就是slot是一个静态的概念,对吧?啊,它是task manager具有的并发执行的能力,我们一般在去配置的时候呢,啊,那就往往就会直接把这一个,呃,就是当前能。
12:26
用的slot你尽量给它用开,那大家看我就直接把这个呃,并行度就直接设成六,哎,那那你看是不是就把整个的这个六个slot都利用起来了啊,那对于有一些特殊的操作,可能我要单独指定它的并行度可能是一啊,可能是别的,这就是实际应用的一个考量。那我们回过头来,大家再想一想,为什么前面我们要要说这个并行度有一个概念,说整个流处理过程当中的并行度是所有算子里边最大的那个并行度呢?啊,这其实就是解决了之前我们提的那个第二个问题,就是说一个流处理程序,我们写完代码之后,到底它要占据多少个slot,对吧,到底分配几个slot它就够用了,到底要分配几个呢?
13:12
诶,我们看到因为slot共享这种机制的存在,这就导致我们分配的时候呢,只要以是不是最大的那个并行度算子,所有算子定义并行度的时候,定义的最大的那个并行度作为标准就可以了。啊,所以我们就把这个并行度叫做当前整个流处理的并行度,也就是我们接下来要给它分配至少要分配的lo数量,你有这么多就能把它跑起来。好,所以对于这个问题而言,之前我们给大家运行的这个这个事例啊,大家还记得,就是当时给大家呃,把这个并行度调成二对吧,我count的时候调成二,当时大家看到我们这里边的任务其实是你看中间这个并行度都是二,其实一共是有六个任务的。
14:02
但是需要有六个lo才能跑起来吗?其实不是的,大家会想到是不是只要有最大并行度是二,每个任务的并行,呃,最大并行度二,那是不是整个流的并行度就是二啊,那所以我们只要有两个slot就能够把它跑起来。啊,所以这是关于这一个运行时候啊,这个到底需要多少资源这样一个问题,我们就把它解决掉了。然后接下来我们再来看一看一个,呃,就是这里边给大家画图来说明一下啊,就是并行子任务到底是怎么去做分配的,这个说的其实就非常的明显了,比方说左边这里边大家看这里边是一个没有拆成并行子任务的一个一个状态啊,这个我们管它叫做job graph啊,就类似于一个,呃,就是只只是一个一个要执行的这样的一个计划啊,相当于是这样它还不是最后task manager能执行的那个每一个任务的那个图,那我们要把它拆成什么呢?拆成右边的这个图,大家看是怎么样分配任务的啊,那这里边我们就看到了啊,按照这个并行度来对吧,这里边整个所有任务里边abcde执行的最大并行度是四,所以说我就至少需要四个slot,而且就是有四个slot就肯定能跑起来了。
15:23
啊,然后这里边我就给了两个task manager,每个task manager里边有两个slot,那刚好就可以跑起来,大家看具体的分配是什么样的呢?大家对于这个A这一步操作,这一步操作它并行度是四,那就一字排开四个A对吧,占据了四个slo,分别占了四个slo,然后B同样啊,你看这里边也是并行度是四,所以一字排开,那C这里边并行度只是二,哎,我们在分配的时候呢,啊,那这个就是你只要是空闲的这个slot,因为可以共享嘛,对吧,就是只要找两个slot直接把它分配过来就可以了。然后接下来D又是变形度是四一字排开,E是两个,哎,这个我们找两个空闲的lo给它直接分配开就可以了啊,所以整体的这个划分就会变成这样的一幅图,我们可以看到在一些比方说在这个。
16:13
呃,啊,当然在这种划分的时候,大家看这个C和E刚好都错开了对吧?所以并不是某一个slo就刚好把所有的这个操作都包含在里边啊,但是在有一些场景下,你是可以保存整个完整的这个啊,这个管道的啊,那至于有些同学说,那你关于这个CN,它到底是呃分配到这个,比方说它有两个,它是优先分配到这个呃,Task manager1上的这个两个还是说先平均的分配到不同的这个task manager上呢?哎,这里边我们在flink里边其实是有不同的配置策略的,你可以去定义,自己去定义这个配置策略,那默认的这个状态是什么呢?默认的状态是不考虑那么多对吧,不去做这个,呃考虑就是我尽量分配到呃分分配到不同的上面,或者是分配到相同的上面,我就是呃,随机的找对吧,就有一个列表,然后说当前的这个空闲的slot哪些是可用的,只要是可用的诶,我直接拿过来,直接给他分配就完事了。
17:13
啊,所以这个看起来就比较随机一些啊,默认的行为其实是随机的啊,大家大概知道这样的一个分配原则就可以了。
我来说两句