00:00
我们已经了解了flink当中检查点保存的基本原理,我们会发现最重要的一点其实就是要确定当前保存的时间点是所有任务都处理完同一个数据的时候。那这个时间点我们会发现,为什么要做这样的选择呢?主要就是为了避免不要出现当前某一个任务处理数据的时候刚好处理到一半,诶,中间我要保存状态,这显然就没有办法恢复了,那就只能是还要把大量的上下文信息都保存下来才行啊。那另外还有一个问题是,我也不能说每一个任务当前都在并行处理吗?他们正在处理的数据有可能是不同的。我不能直接就把当前数据处理完就进行保存,因为当前数据处理完了之后,我还得保存到底当前是第几个数据,这样的话,我才能知道接下来哪些数据该处理,哪些数据不该处理,哪些数据要重放,哪些数据不重放。
01:02
而在处理的过程当中,还会涉及到如果在路上没有经过处理,前一个任务处理完了,后边又没有处理的这些数据,那就相当于被丢掉了啊。所以为了避免这些特别复杂的情况,需要保存上下文信息的这些情况,我们就直接让所有任务都处理完同一个数据这个时间点,这是完全确定的。如果说发生故障的话,我们接下来就是在这个数据之前的数据那就都已经保存过了,而在之后的数据呢,那就相当于都没有保存,我们就全部重放就可以了,这是进行检查点保存的一个基本思路。如果类比前面我们提到的做合照的这样一个日常生活场景的话,那我们也可以想到就是如果说某一个班的同学要毕业了,要拍毕业合照的话。最好的方式当然是让大家都是当前是同一个状态,就都是已经通过了毕业答辩啊,都已经完成了论文,做了毕业答辩之后,要毕业的之前的那同一个状态,这样的话主要是方便之后如果我们。
02:10
拿出这样一张照片的话,就会知道当时我们的状态都是同一个状态啊,这样就方便恢复嘛。而如果说我们想要拿到的这一个状态,每个人当前的。工作的节奏,工作的节点都不一样的话,有些同学可能论文才写了一半,有些同学论文已经写完了,但是还没有通过答辩啊,那这样的话,我们最后如果恢复出的状态,那也得是五花八门,这个就非常的麻烦,所以我们现在的状态,那就是让所有同学都通过答辩之后,再来一起拍一张合照。但这里面又有另外一个问题,我们仔细思考就会发现,如果说让所有同学都完成答辩之后才来拍合照的话。那每个同学还是有快有慢啊,本身我们现在这个任务是并行处理的,所有的任务本来就有拓扑结构上的先后顺序,那另外呢,有些还快一点,有些还慢一点,那自然处理完同一个数据的时间点是不一样。
03:16
那所以如果说每一个同学完成答辩的时间不一样,我们就只好先完成答辩的同学就等着放在这个例子里边,那就是SOS任务已经读完第三个数了。但是你不能保存,你就先等着,等什么时候呢?等到后边的所有任务都把第三个数处理完了,这个哈,都处理完了,我们再统一做保存,这就是我们按照生活场景能够想到的,哎,所有的同学都要等着完成毕业答辩了,这个时候我们再把所有人集中起来,排好队,然后咔嚓一张合照拍出来。这种方式显然是会影响我们整个系统的性能的,因为在这个过程当中,本来前面的任务都已经做完了啊,我都已经答辩,都已经完成了,但是我不能做别的事儿,因为如果要是继续读取。
04:09
接下来的数据的话,那我的偏移量就改变了,就变成四了,变成五了,那就不是我们想要的,我们要最后大家都是处理完第三个数据之后的状态,哎,那所以这就会导致等待当前的资源就会浪费。所以我们就想到了,能不能有更好的方法把这个过程优化一下呢?其实优化的手段也比较简单,那就是我们发现在流处理里边其实非常的非常容易实现,就是我根本没有必要让之前的任务停下来。因为当前如果说任务已经处理完,SS任务已经读取完了第三个数的话,天移量已经达到三了,诶那我就可以直接把自己的状态单独做一个保存不就可以了吗。不需要别人啊。
05:00
只要我发现自己已经处理完第三个数了,就做一个保啊,那map这里是没有状态,如果它有状态的话,也是处理完第三个数据哈,处理完了我就把他的状态直接保存就可以了。而后边的这个sum任务也是一样的,只要发现第三个数据都已经处理完了,就把自己的状态单独做一个保存。所以整个的这个过程呢,这就变成了一个完全异步的过程,如果对比我们生活当中拍合照的话,那就相当于不需要把所有的人都集中在一起去做拍照,而是每位同学完成答辩之后,我们就把。自己当前的状态保存下来,就去拍一张照片就可以了,然后最后只要把所有人的照片再拼在一起,这就是一个完整的。合照啊,当然了,实际生活当中我们并不会去做这样的一个事情,呃,一方面是因为拼合照的这个代价比较高,比较麻烦,但是对于计算机而言,对于我们的flink系统而言,这个显然是非常简单的照manager那边有我们完整的拓扑结构,每一个任务做完了之后,只要非常简单的按照ID把它们。
06:17
对应关系拼接在一起就可以了啊,所以这个思路是完全可行的。那具体在flink当中检查点其实是有完整的一整套算法的啊,它其实应用的是基于昌迪兰波特算法的一个分布式快照算法啊,接下来我们就来详细的了解一下。那在这个算法里边,最为核心也是比较重要的一个概念是所谓的检查点分界线RY,那什么是检查点分界线呢?啊,我们这里面首先要考虑到现在最重要的目标是什么,我们现在最重要的目标其实就是不要暂停流处理,也就是每一个任务都是。
07:03
处理完当前我们想要截止的那一个数据,那处理完了之后马上就保存当前的状态,那这里的要求就是我们得让每个任务认出要触发保存点保存的那个数据。但是这个就稍微的有一点麻烦,我们会想到,那就应该正常想法的话,应该是在数据里边添加一个特殊的标志表示,比如说在前面。我们的第三个数据这个哈,这个数据里边加上一个标记说,哦,当前这是一个做完这个数据要去保存检查点的这样一个数据。这是能够想到的,但是如果有时候因为我们检查点是周期性去做的,并不是来一个数据就做一次,所以有时候要做检查点的时间点。有可能就根本没有,当前就根本没有数据。而前面如果能插入数据的那个。
08:01
时间,如果能插入标记的那个数据,相当于我们之前都已经处理完了,那就只有等到下一个数据来的时候才能插上这样一个标记了啊,这样的话就不符合我们真正意义上的周期性触发检查点保存的这样一个策略了。那怎么样能够避免这种情况呢?我们可以借鉴一下之前map的生成的方式。之前我们water mark其实并没有完全依赖于数据,而是在本身的数据中间插入了一个特殊的标记,而我们把它当作当前,只是当前时间的一个watermark。所以现在在flink进行检查点保存的时候呢,也可以插入在数据流里边入一个特殊的数据结构,专门用来表示触发检查点保存的时间点,也就是说后边的任务我不需要去看当前数据到底是哪一个,也不需要看当前数据有没有特殊标记。
09:07
我只需要。按照正常的流程一个一个数据去去处理,当处理的时候发现了特殊的这样一个。数据结构的时候,我就知道当前应该做快照保存了,就把当前所有的状态保存到检查点里边,提交给外部的存储系统就可以了。哎,那所以我们就会发现在这个数据流里边,以当前的这个标记为界,那其实之前所有数据带来的状态改变就都会保存在当前这个检查点里,而之后的所有数据呢,那就相当于就不包含在当前检查点里了,所以我们会发现这个标记就代表了一个检查点的保存的时间。那这样一个特殊的数据形式,我们就把它叫做。
10:01
Checkpoint barrier就把它叫做一个分界线,因为它在数据流上相当于把前后的数据按照不同的检查点给分分开了,所以把它叫做分界线。当然了,本身Barry在英文里边有有篱笆,有障碍,有各种各样不同的翻译和解释,那这里的话,我们可以认为它就是一个分界点啊,所以直接就把它翻译成分界线。通过前面的定义我们也可以看得出来,就是跟水位线其实是非常的类似,检查点的分界线呢,也是一条很特殊的数据,它是由S算子注入到常规的数据流里面的,它的位置就是限定好的,什么时候插入这样的一个特殊的数据呢?那就是当S算子收到job manager发出的触发检查点指令保存的。那个指令命令的时候,就把对应的一个barrier插入到当前数据流里面。接下来这个barrier就像。
11:04
普通数据一样,在我们当前的数据流里边向下游流动就可以了。那那所以这就是一个标准的分界线。他按照检查点可以把我们一条流里的数据分开啊,接下来我们可以看一下检查点去进行保存的具体流程,我们可以看到。还是之前那个例子。在第三个数据。完成之后,我们希望去保存一下当前的状态,所以呢,当前barrier插入的时机就应该是S任务,读取了三个数据之后,Hello word hello3个数据之后,这个时候manager做了一个检查,点出发。插入了一个。然后接下来我们可以看到啊,当前SS任务插入barrier的时候呢,自己当前的状态已经是三了,表示已经读取了三条数据了。
12:04
而后边呢?我们会发现后边的任务他有可能根本没有处理完第三条数据,因为我们是先后有顺序的嘛,而且大家都在并行,所以他们各自处理,各自就可以并行不备,那这个时候S任务收到了barrier,那么接下来他就把自己的状态做一个保存。自己的状态是三啊,保存到对应的位置。现在后边的所有的任务,他们根本没有受到这个指令的影响,该干什么继续干,我们可以看到map任务这里边呢,哦,第三条数据哈刚刚到map任务这里还没处理完呢,而后边的萨任务呢,已经处理完了,第一条数据哈一已经输出了,在这里有一个哈一,而第二条数据这个word它还没有处理完呢。所以这里边我们看到本身的状态这里还是HELLO1WORD0啊,那其实我们知道还没有处理完的话,可能这个连word这个都没有,但是要处理完了之后才会有WORD1对应这个状态出来。
13:09
接下来。我们就会发现当前barrier第一个S任务处理完成之后,那就会把它。当做普通数据一样,继续向下游传递。而下游的每个任务呢,也是在收到Barry这样一个标志的时候,才去把自己当前的状态去做一个检查点的保存啊,所以我们就会发现了,当每一个任务下游任务收到barrier的时候,因为我们就是数据流里边插入的barrier了。那当他接收到Barry的时候,显然之前所有的数据都已经处理完了,那当前的状态就应该是已经处理完之前所有数据之后的状态,这是符合我们的要求的。啊,那所以如果要是对比去拍合照的话,这就是让每个人完成答辩之后,不用管别人。
14:07
只要完成答辩,我就去自己拍一个毕业照,最后只要交给班主任老师统一把大家的单独的毕业照拼在一起,拼在一起,然后合成一张合照就可以了。啊,这样的话就等省去了每个人等待集合的这样的一个时间,啊,那我们自然会想到在计算机系统里边分布式架构,这个是非常有意义的耗费的时间,那是班主任老师P图的时间,对于flink系统而言,这是job manager的时间。而省去的时间呢?是每一个任务等待的时间,这是我们task manager每个slot上真正处理数据的时间,这个显然会更加重要一些。这就是关于检查算法里边barrier的定义和整体的处理思路。
我来说两句