00:00
我们已经了解了flink当中算子状态的用法,哎,那我们知道算子状态最大的特点就是每一个状态实例,它的作用范围就局限在。当前分区的并行子任务上,哎,那在同一个分区里边的所有数据都能访问到相同的状态,那分子状态里边呢,我说可以分成三类,一般情况我们所使用的就是list state列表状态,那union list state呢,它跟列表状态基本上是一样的,只是在进行并行路调整的时候会更加灵活,稍微麻烦一点,它会做一个联合重组这样的一个重组方式。那除了这两种算子状态之外,最后还有一种比较特殊的状态,就是广播状态broadcast state。那关于广播状态,其实前面我们也提到了啊,广播状态顾名思义那就是状态会被广播到所有的并行子任务实例当中,哎,那所以每一个并行子任务上能够访问到的状态都是一模一样的啊,所以可以认为啊,所有数据都能访问到相同的状态,那这种类型就叫做广播状态。那如果要是做并行度调整的时候,也非常的简单啊,因为完全都一样嘛,那如果说调大或者调小的时候,就直接复制或者删除一份状态就可以了。
01:28
广播状态从概念上其实非常的好理解,但是呢,它在代码具体调用的过程当中,稍微还是有点复杂的,所以接下来呢,我们在专门针对广播状态进行一个讲解。呃,前面其实我们介绍两条流进行连接操作的时候,也简单的提到过广播连接流这样一个概念,哎,那广播连接流和广播状态其实就是密不可分的啊,他们其实就是放在一起去使用的,那我们会想什么时候会用到广播状态呢?那就什么时候我们需要把同一份状态,让所有的并行子任务都保持相同的东西,让他们都知道这样的一个一份数据呢?
02:11
诶,那一个最普遍的应用就是所谓的动态配置或者动态规则,诶,这指的是我们一般情况在处理数据的时候啊,有时候可能我们需要提前做一些配置,或者说制定一些数据处理的规则,诶那这些配置或者规则如果说它是静态的,也就是说定死了的,那我们自然可以把它直接放在配置文件里面,哎,一开始创建任务的时候,我们从配置文件里边读取出对应的配置项,然后接下来一次加载之后永久就有效了啊,我们就按照这个规则,按照这个配置去处理数据,但是。有时候我们的需求可能是这个配置或者规则,它还会动态变化,那如果它随着时间会发生变化,又应该怎么处理呢?啊,那这里一个想法,简单的想法,那就是我们把它放在配置文件里边,那就定期去扫描嘛,另外起一个进程去扫描它,如果发现了改变,那我们就重新加载。
03:14
但是这种方式,那就是我们得有另外一个程序来做这样的一个扫描工作,而且呢,这个扫描周期还比较有讲究,如果说我们隔的时间太久,那就有可能导致这个配置更新的不及时。那如果说扫描的时间太短,非常频繁的在做扫描的话,诶,那中间这个配置更新毕竟不是那么频繁的一个操作啊,那中间可能我们就做了大量的无用功,耗费了大量的系统资源,诶那所以这个时候我们到底应该怎么做呢?啊,那有一种想法就是我们可以借鉴之前所谓的事件驱动的思路,当前有一个配置文件我们可以。不需要不停的扫描它,不停的扫描它,我们可以把它当成一个事件去进行触发,那就是当它发生改变的时候,我们产生一个对应的数据,把这个数据读进来,那相当于我们现在就有了一个新的数据,触发当前的一个操作,更改配置或者规则,影响后边我们的数据处理就可以了。
04:17
所以这样看的话,我们这里的配置文件的读取相当于就是。读了一个流进来,哎,所以这是一个特殊的数据流,把这个动态的配置项或者是动态的规则项就当成了一条数据流。啊,那我们就想到了,那对于这一条流里面的数据啊,我们把它读取出来之后,哎,比方说另外还有一条流,这是我们正常的要处理的数据,我们就姑且把上面这条流叫做规则流或者叫配置流吧,这条规则流里边的数据我们应该全部读出来之后,啊,是要。相当于叠加在我们真正的数据流上面,而且这个数据流这里如果有多个并行子任务的话,很显然这个规则项或者配置项是应该广播给他们的,他们应该是保持着同一份对应的配置或者说规则,哎,那所以我们看这明显可以用一个广播状态来进行实现了。
05:17
所以这就是广播状态一个非常经典的应用的场景,那这个过程当中,首先我们相当于是需要定义这样的一个广播状态,定义了广播状态,然后把它跟我们本身的这条数据流里边这条规则流或者叫配置流跟广播状态结合在一起之后,就得到了一个所谓的广播流broadcast stream。然后呢,哎,我们还需要把这个广播流和普通的数据流要连接在一起,做一个合流操作,Connect就得到了所谓的广播连接流,那这一部分其实之前我们在介绍connect的时候也简单的做过讲解啊,接下来相当于我们再来回顾一下。
06:02
在代码当中调用的过程呢,就是这样的,那底层广播状态是用什么状态类型来实现的呢?它是一个map state啊,所以我们在代码当中是首先要去创建一个map state的描述器script,也就是说底层的这个广播状态我们是用key value啊建值对这样的形式去进行描述,进行保存的。我们定义了mapscript这个描述器之后,那接下来呢,对之前我们所谓的规则流,这条数据流调用一个点broadcast方法,那这个方法哎,我们知道啊,本身broadcast可以用作数据的物理分区,那也可以用作产生一个广播流broadca stream。那这个时候呢,传入的参数就是上面我定义好的map script这个描述器。这样就得到了一个广播流,然后接下来呢,得到的这个广播流就可以跟我们所要处理的数据流做一个连接操作,Connect连接起来之后得到的就是所谓的广播连接。
07:12
好,那接下来广播连接流可以执行的操作呢?诶,那当然了,经典的就是一个process这个点,Process里边传的参数就是我们所谓的broadcast process方式,这就是前面我们提到的处理函数大家族里边。最后的两类啊,那broadcast process function和key broadcast process function,这就是我们在代码当中去对广播状态去进行定义和处理过程。那具体处理的逻辑呢,当然就是应该在这个broadcast process方式里面去进行定义了,这一个process方式呢,它里边最核心的抽象方法也是有两个啊,那跟其他的处理函数非常类似,它也有一个process element,这个process element处理的就是我们前面这个正常的数据流里面的数据,哦,那我们知道collect本身这个连接之后是一国两制嘛,那另外一条流,我们这个广播流里的数据,这个都是配置项啊,动态的配置,动态的规则,那这个数据又怎么处理呢?这个来了之后,它进入的方法是这里的process broadcast element啊,所以是广播出来的元素去进行单独的处理。
08:27
这样的话就分开对两条流里的数据分别去进行判断,进行处理、计算。是整个的处理流程。
我来说两句