00:00
到目前为止,我们已经了解了flink当中的转换算子的应用啊,我们主要介绍了基本转换算子和聚合算子,这是转换算子里边的两大类型啊,那后面呢,我们又把它抽象出来,提炼出了更加通用的用户自定义函数类进行了详细的介绍啊,那当然了,我们还可以使用负函数类rich方式进行功能的扩展,那在本节的最后呢,我们再来详细介绍一下另外一大类算子,那叫做物理分区算子。所谓的分区positioning其实是大数据处理当中的一个非常常见的概念,因为我们知道在大数据处理里边,我们当前的数据非常多,是海量的数据,所以一定是会进行分布式的并行处理,我们要把它分发到不同的并行子任务上,那对应在flink架构里边呢?哎,那我们就知道了,有多个task manager,每一个task manager上又有多个不同的slot,每一个slot上就可以运行一个并行的子任务,哎,那所以我们当前同一步任务,比方说我们当前是一个map。
01:10
并行度为四的话,那就有可能有这样的四个并行的子任务分别在四个slot上执行啊,那接下来我们就会想到了它的上一步操作,假如说哎,我们之前就是一个SS算子直接读取数据源。那数据读取进来之后,是怎么样分配到不同的map子任务上的呢?这就涉及到了一个数据的重新分区的操作,所以简单来讲就是说在流处理任务上下游之间,它需要涉及到数据传输的一种重分布的方式。这种数据的重新分布的方式,我们就可以把它叫做分区操作,所以这样看的话,这个概念我们并不陌生啊,之前讲到的聚合算子前面啊,先介绍的这个K,其实它就是一种分区操作,我们说在聚合之前先要做分组,先要做KBY嘛,他所做的事情呢,其实就是把我们当前的数据。
02:10
按照某个字段某个K,然后进行了逻辑上的分组,那那我们知道当前岔开的这两支,它并不是分成了两条流,当前我们其实还是一条流,但是呢,这一条流里的数据在我们并行执行的时候,可能就会被分发到不同的slots上面啊,这就是我们所说的分区操作。当然了,KBY其实相对来讲还是比较特殊的,因为我们说这个KBY呢,比方说诶,我当前这个K如果是以user作为一个当前分区的K的话,哎,那么我并不能指定说当前user如果是Mary的话,就一定到第一个分区啊,如果是Bob的话,就一定到第二个分区,我没有办法这样去指定,只能是按照底层架构的逻辑啊,我们说是按照这个K取它的哈希值,然后对于当前的分区数进行一个取模运算,最后做一个自动分配。
03:07
啊,所以之前我们也强调了,每一个K对应的数据一定会被分到同一个分区,但是呢,不同K的数据未必是可以分得开的,有可能不同的K它也会分配到同一个分区里面去,因为他做了曲模嘛,是有可能出现重叠的。所以从这个角度来讲,KBY应该说是一种逻辑上的分区操作,它只是逻辑上把这个数据分开了。至于说呃,到底分到哪个分区分的到底均匀不均匀,这些其实我们是完全没有办法去控制。所以接下来我们想要介绍的这一部分算子呢,那就是所谓的更加硬核的分区操作,我们对应的可以把它叫做物理分区,也就是说在这一部分算子里边,我们可以真正意义上的去控制分区的策略,也就是说,哎,告诉当前的数据。
04:01
这条数据来了之后,我要明确的告诉他,接下来下游,比方说有四个并行的子任务。不要告诉他到底分配到哪一个分区去,哎,这就是我们当前物理分区所要做的一件事情。那这种操作到底有什么实际意义呢?诶,我们可能会觉得,诶这个好像没什么意义啊,按照KBY,我们按照K直接把它分开不就行了吗?仔细一想的话就会发现在实际应用的过程当中,按照K。直接做逻辑分区的话,那就有可能会出现某一个K的数据有可能非常的多。而另外一个P的数据呢,有可能又非常的少,那这个时候我们直接把它做这样的自动分区,逻辑上把它分开的话,就有可能会出现很多数据都堆积到了某一个分区,而另外的分区闲着,哎,这就是我们所说的数据倾斜。那在实际应用的过程当中,肯定我们是要避免这种情况的啊,因为这样的话,相当于我们很多资源浪费了,没有利用起来,而有一部分资源呢,又不够用,成为了我们整个系统的瓶颈,所以我们要避免它,想要避免数据倾斜,一个常见的手段呢,就是针对当前的T做一个更加复杂化的,更加均匀化分布的一个设计啊,比方说我们可以不要使用单一的K,我们可以使用组合K,把它设计的复杂一点,尽可能的均匀分开啊,那另外呢,我们还可以直接使用这种比较硬核的直接指定分区的策略,这就是我们所说的物理分区算子啊,那当然了,在实际应用的过程当中,其实啊,这个物理分区有时候是在我们不知不觉的过程当中就已经发生了,比如说什么呢?就是我们说的并行度变化的时候。
05:45
比如说我们上游一个算子啊,前面我们说的S。读取数据源的时候,当前假如说这是一个不能并行的SS任务啊,所以当前并行度只是一只有一个子任务,而下游的map呢?
06:01
它有四个并行的子任务,如果是这样一种场景的话,那很显然我就得去明确当前SS读进来的数据,每一个到底分配到哪个分区里面去。那其实我们能想到啊,那正常情况下肯定就是,诶,我来一个就先分配到第一个,然后再分配到第二个,把它尽量均匀的分开,这样不就可以了吗?啊所以在flink实际应用的过程当中,涉及到并行度调整,上下游任务之间并行度变大变小的时候,都需要考虑数据的分区操作啊,我们要把它做一个均匀的分配。对于物理分区操作呢,在代码当中应用也是非常的简单,呃,就像前面我们说的这个KBY啊分组操作一样,它就是直接基于一个data stream调点KBY方法啊,那物理分区操作也是直接基于一个data stream去调某个方法就可以了,所以我们可以认为当前的物理分区也是一个特殊的算子啊,在有一些资料里面会把它叫做物理分区算子啊,但是我们会发现啊,它跟前面我们介绍过的转换算子还是有所区别的,因为像前面我们说的map flat map filter,或者说聚合这些算子,它其实都是要针对当前的数据。
07:23
做一个转换处理的啊,即使是filter,那它至少也是要是否过滤啊,有这样的一个操作的,它是针对每一个数据做操作的,而现在的物理分区呢,它不会改变数据,只是会把当前的数据分发到不同的下游子任务上啊,所以理论上来讲,这个物理分区并不是一步任务,不是一步操作,它是决定两个任务之间的数据传输方式。啊,所以我们应该把物理分区和一般的转换算子要区分开,尽管在形式上他们都是直接基于data去调一个方法就可以了,而且我们还要区分开,就是我们这里讲的物理分区操作跟KBY是有所不同的,因为KBY调用之后得到的是一个k stream。
08:12
而物理分区操作呢,调各种方法调完了之后得到的仍然是一个data,而且里边的数据是完全不变。这就是我们所说的物理分区,它只定义了上下游任务之间的数据传输方式。这是整体的介绍,那接下来呢,我们就来分门别类的讲一讲各种不同的分区方式。
我来说两句