00:00
接下来我们讲flink里边的容错机制啊,那这一部分呢,主要是就是给大家讲所谓的checkpoint了,一致性检查点啊,然后呢,大家看一看怎么样从检查点去恢复状态,呃,然后这一部分很关键的一点是。Flink里边到底是怎么样去用,呃,这个checkpoint保存了整个状态的一个快照的啊,这个是要给大家讲一讲算法的一部分啊,最后再说一下福林里边比较有特色的一个保存点的一个机制,呃,这是我们这节课的主要内容,首先是这个一次性检查点啊,那。其实我们之前一直在跟大家说,这个flink里边提供了这个很严格的状态一致性的保证,对吧,它能够有这个从故障中恢复到之前状态的这样的一个机制,那么flink里边故障恢复机制的核心其实就是所谓的状态一致性检查点啊,就是大家经常可能会看到这样一个一个名词,Checkpoint,因为在呃,Spark里面也有这样的概念,对吧?啊,所以这个概念大家并不陌生,那flink里边它的checkpoint又有什么样的特点呢?
01:16
这个大家要注意一下,因为flink是一个有状态的流式处理的一个大数据框架,那么有状态的流逝的应用,那么它上面的拆框的,它的检查点到底是要保存什么东西呢?它其实就是要保存所有任务的状态,在某个时间点的时候的一个快照,或者说一份拷贝,对吧?那它其实保存的就是所有状态的一个快照。啊,那大家想一下这个时间点到底应该是怎么,怎么定义呢。是说,哎,我这里就是说所有所有人现在站好,哎,大家都不要动,然后123我喊茄子,大家笑一下,然后一起拍个照片吗?所以就是说在这个流失处理的过程当中,我是直接喊一下123停,大家全全停下,都不要动,都不要干活了,然后停止下来,就这个时间点,你现在的那个状态是什么,我就把你抓出来,是这样做吗?
02:21
其实是有问题的,因为你只抓的是状态,你并不知道现在他到底处理到哪个数据了,对不对。那假如说你是让所有的状态同时停下来,然后把他们当前同时的这个时间点。的状态拿出来的话,那是不是有可能,而且不是不是有可能哈,是一定的,前后不同的任务,他们处理的数据其实是不一样的呀。那他们当前的状态,其实表示的是不同的数据处理到某个阶段时候的一个状态啊。哎,那所以这个时候你如果把它们保存成一个状态,到时候从这个状态恢复出来的话,是不是就有一个问题,那当时那个数据到底处理到哪儿了呢?那个数据到底是在我前面第一个任务上处理完了,还是说他已经第二个任务上处理完了呢?还是说我所有的任务都已经把这个数据处理完了呢?
03:20
是不是我们根本无从知晓啊啊,所以大家要注意,在牛市处理里边,如果我们不想保存当时的数据的话,当时所有的数据的话。我们是不是应该按照什么时间点来保存这个快照呢?我们所谓的同一时间,同一时间点就指的不是我们所谓的啊,就是在这种物理意义上对吧?同一时刻,我这里让所有的任务停下来拍个快照,而是我是要让数据流动,流动到所有任务都刚好处理完某一个数据的时候,这个时候把他们的状态都拍下来,是不是这就确切的能保证诶,他们的状态都是处理完某个数据之后的那个状态啊。
04:14
所以这个数据我尽管没有存,但是我知道它肯定已经处理完了,对不对,哎,所以这样的话,我们到时候恢复就能完整的恢复到之前的状态,这是这个流式处理过程当中,这个一次性检查点保存的一个特点,它的快照机制的一个特点啊,所以。在这里给大家看一下啊,就是在执行流应用程序期间,Flink它会怎么做呢?啊,它会定期的去保存状态的一致性检查点,那如果要是发生了故障的话,Flink就会用跟当前最近的一次成功保存的那个checkpoint来恢复。我们应用程序的状态,然后重新启动处理流程,那当然了,这个重新启动处理流程是可以在就是它的启动的策略是我们可以去做配置的,可以在配置文件里面配置,也可以在代码当中去指定啊,这个稍后我们在代码里边给大家去做一下讲解啊,这里边我们主要是给大家讲这个check po里的机制,那大家可以看一下这个图,大家看看这个例子啊,这个例子是什么呢?这个例子是大家看这个这个流其实很简单啊,这个流的数据,这个不是代表时间戳,这个就代表它的自己的数据,我们当前的数据就是就是一组数对吧,那简单来说它其实是。
05:40
从一开始的自然数构成的一个数据流,而且就是按顺序排好的,所以这个场景就非常简单了,123456789来了,呃,那那大家看他后面要做的任务是什么呢?首先数据源来了之后,是不是这里边应该有一个SS任务啊,对吧?这里边先把它这个S读进来,然后接下来。
06:05
大家看后面有有一个任务做sum,这个sum是根据什么来做sum呢?对,根据不同的基偶,根据奇偶性分类来做萨,所以它相当于是上面这个子任务是加所有的偶数,下面这个子任务加所有的奇数,对吧?呃,它是这样的一个状态,那大家看一下现在的状态是什么呢?一。啊,现在简单的状态,哎,大家先看一下这个上面上面这个图啊,我们先看一下这个图。这个图其实。哦,刚才我是跳了一页PPT是吧,所以大家看一下,就是说我们这个图里边,它其实表示的是什么呢?表示的当前处理的状态,应该是处理到哪里了。
07:04
其实就是啊,因为我们说这个图里边,它的数据源其实就是从一开始123456789这样的一个自然数构成的一个呃,一个数据流对吧?啊一个一个输进来,然后前边这里的任务是SS任务,把数据读进来,后边是做一个sum计算求和,按照奇偶性分类对吧?上面这个子任务对所有偶数求和,下面这个子任务对所有的奇数求和,所以大家看一下现在这个状态它是进行到哪一步了。是不是,诶大家看这个数据源这里,诶接下来是六和七,那是不是应该是五已经读进去了呀,对吧,那大家看一看你之前的数都已经处理完了吗。诶大家注意一下,这里边S这里自己保存了一个状态,保存了一个什么状态呢。
08:08
是不是就是当前读入我们这个圆这里的偏移量啊,它并不是保存当前的那个数据,对吧?因为是不是我们这里是自然数,就是按照顺序排好的自然数不重复,那正常我们发过来的这个数据,数据流里边的数据是不是有可能是一样的数啊,这个我们没保证对不对,你做word count有可能过来就是一样的word嘛,那所以这里边它要保存的其实是对本身数据源的一个偏移量offset,那既然这里边偏移量已经是五了,是不是他已经把五这个数据读进来,而且已经处理完了,对吧?好,那然后大家继续看后边啊,上边的这一个偶数的这个求和sum,这个结果是六。大家想一想,1234567这个数,那是不是就二加四前面的数都处理完了呀,二加四等于六对不对?那下面是奇数求和九九的话,哎,那是不是135加起来就是九,是不是都处理完了呀?所以当前这个状态其实就是对,是不是五这个数所有的任务都已经处理完了,对吧?从头到尾都处理完了,所以我现在要保存的状态是什么呢?
09:29
要保存的就是。哎,所有数据,所有的任务,把五这个数据都处理完之后的这个时间节点的状态,哎,所以我要保存的状态是什么?S任务存偏移量五。然后呃,这个some even就是就是我这个偶数求和的子任务保存状态是六,奇数求和状态保存是九,它们三个存在我们的状态后端里边,对吧,然后就构成了当前这个checkpoint啊,所以当然就是说状态后端里边肯定是专那边它有一个这个数据结构的定义,对吧,我得知道哪个存的是S,哪个存的是这个some even这个任务的,哪个是some out的,呃,然后具体存储可能又在另外的一个地方存,呃,它是这样的一个数据结构。
10:22
好,那然后接下来大家再看一看,在这种情况下,如果说出现故障又怎么办呢。大家看一下。在执行这个流应用程序期间,Flink它会定期的去保存这个checkpoint的,对吧?然后如果要是发生了故障,那就得用最近成功保存的那一个checkpoint来恢复应用程序的状态,然后重新启动应用流程,呃,那么在这个过程当中,大家看一眼这个图啊,这个时候如果要是说七这个数据来的时候,大家看,诶大家看现在这个状态是什么呢?那七之前应该还有六啊,六处理完了吗?诶大家看六是一个偶数,那是不是萨even这里边之前是六,现在已经加到12了,那说明六已经处理完了,对不对?那七处理完了吗?七没处理完七哎,但是七是真正就没有读进来吗?已经读进来了,SS任务是不是已经偏移量改了,而且已经把这个是不是朝下传了。
11:30
但是在这个过程当中,对挂了后边这个Sam out这个任务挂了这个task manager出现了故障,那怎么办呢?然后始恢复,那那大家想我们现在如果要恢复状态,应该恢复到什么呢?啊,有些同学说,哎,你七挂了,那你应该恢复到七码,应该是把当前这个七十二九保存下来去恢复一下吗?可以这么恢复吗?对这个大家要注意,你假如这么恢复状态的话,那是不是相当于圆,这里边认为漆已经处理了,但是后边七其实没处理,对不对,那是不是七这个数就相当于丢了呀,所以他的操作其实是什么啊啊,当然有同学说应该是恢复到上一个刚刚处理好的那个那个,呃,数据对吧,应该是处理到六的那个状态,但是我们的那个。
12:30
Checkpoint是不是不能保证每一个数据来了都做一次checkpoint啊,这个数据量大的时候,你这个就就代价太高了,对不对,每个数据来一次都都做一次checkpoint,所以我们往往是隔一段时间做一次checkpoint,那这样的话它应该恢复到什么时候,上一次最近的那个checkpoint,对,那就是五是不是?那当然这里边如果要是遇到故障之后,第一第一步要做的是不是就应该是先重启应用啊,那当然这个重启应用有各种各样的重启策略啊,这个后面我们再给大家讲啊,那首先是重启应用,然后大家会看到圆这里是不是还是这样的一个偏移量,对吧?之前七以前的数全已经来过了,八和九还没有读过,然后接下来干什么呢?接下来是不是要从。
13:20
上次保存好的那个最近的一次checkpoint读取状态,读出来的状态是569,然后根据这个SS任务,是不是根据他的这个状态要把我们的S那里要去重置,重新提交偏移量啊。啊,只要我们的SS任务是可以重置偏移量的,那么是不是这里边就相当于它要恢复到之前五已经处理完了六七的那个状态啊,就又恢复到这个状态,所以大家看这个状态是不是跟我们当时保存checkpoint的时候那个状态是完全一样一模一样啊,所以接下来再继续从圆里边去读六读七,是不是就一点问题都没有了啊,所以接下来我们继续把六和七正常的读取,然后正常的处理,这样是不是就恢复应用的啊,正常处理过程了,对吧?大家看上面加了一个六,下面加了一个七,对不对啊,这个就是正常的一个处理结果了,好,那呃,当然了,就是说大家会看到啊,就是这里边我们提出一个概念,就是说这种checkpoint的保存和恢复机制,它就为我们这里边的应用程序提供了所谓的精。
14:42
确一次的状态一致性,保保证所谓的精确一次,英文是exactly once,这个可能是后面我们会反复给大家提到的一个概念啊,Exactly one,呃,那因为所有的算子啊都会保存。当前的任务,那就是当前任务的状态,然后把它放到检查点里面去,然后在故障的时候就会把它恢复出来,对不对啊,这样只要我们输入那边还能够重置这个状态的话,重置偏移量的话,那就可以重新。
15:18
恢复这个当前我们当时我们做拆的时候那个状态啊,重放。就是在这个过程当中,我们没有正常处理的那些数据啊,这就是这个过程,所以在这个过程当中,相当于我们是做到了精确一次,精确一次是个什么意思呢?它其实表示我们数据不会丢,而且数据只处理一次,哎,这个过程大家可能就会想这个不对啊,你这个过程其实并不是数据只处理一次啊。因为这里边如果要是你恢复到这个当时五处理完之后的那个状态,那六这里不是已经处理了两次吗?诶,但是大家注意这里边对大家想我直接已经把它恢复到12了,那你想这个状态都已经恢复了,那这个跟之前没有处理六有什么区别吗?
16:12
是不是相当于没有区别啊,相当于还是恢复到之前的状态了,所以在这个意义上,其实它是确实在内部保保证了所谓的精确一次的exactly。呃,当然这里边就埋下了一个伏笔,就是说大家会想到我为什么说是在内部保证了精确一次呢?言下之意就是,如果你要想把这个输出到外部的话,是不是就会有问题啊,大家试想一下,假如说我这里边有一个thinkink,后面又连了一个SK任务对吧?那我已经把这个,假如说我连了一个数据库对吧?或者连了一个卡夫卡,我已经把它写到卡夫卡里边去了,已经被别人消费掉了,那你这会儿再来一次,是不是相当于又消费一次啊,啊,对,这个当然就会有问题,这可能就不是所谓的exactly ones了啊,那怎么样实现这样的一个that ones,我们后面再还会给大家详细展开讲啊好,然后我们接下来大家就会想到,那既然这个flink里边它的checkpoint看起来还是就是能实现这个很很强大的功能呢,能保证这个整个过程当中的one,那具体实现到底是应该怎么样去实现呢?
17:27
诶,这里边就涉及到这个检查点,具体的实现算法,我们首先可以想到一个最简单的实现方法,不知道大家能不能想到啊,其实最简单的想法非常简单,就是。好,现在我把所有的任务全给我停止,然后直接去拍快照,对吧?啊,就是直接全停下来,谁都不要动了,我直接去拍快照啊,当然大家想到那不对呀,我们前面说了,你是以这个处理完一个数据作为一个时间点呀,对吧?啊那那也好办呀,我是不是可以按照对,就是处理完你当天全停下来了对不对,然后我再去查看看哪一个数据是当前刚好所有都所有任务都已经处理完的那个状态,正在路上还在处理的那些状态,呃,那些数据我都丢掉对吧,都不管,我只存就是之前那个已经就是已经处理完的那些数据的状态,但这里还有一个问题,就是说,那那如果要是说当前已经有些任务,他已经处理到后边的数据的话。
18:37
那是不是相当于那个状态已经变了呀,你是不是还得再让那个状态再回退,才能够把这个状态完整的保存下来呀?哎,这就有点麻烦了,或者另外一个考虑是,那我能不能不去回退状态呢?不去回退状态也可以,那你就直接全部停止下来之后,再把所有的那个当前的它处理到哪个数据也保存下来,对吧?啊,这是另外一种实现,那当然了,这种算法显然是不太好的。
19:10
一种,呃,一方面的考虑就是因为你要额外保存很多东西,对吧,不光要保存状态,你还得保存数据,另外一个考虑是这种思路,它其实是就像我们不知道大家是不是比较比较喜欢拍照啊,呃,就是有些同学可能比较喜欢拍照,有些同学不喜欢,其实我见过有些有些有些同学啊,有些朋友他即使是喜欢拍照,他也不喜欢拍大合照,为什么呢?因为大合照他得要求对,他得要求所有人都都齐位,对吧,所有人都停下来,都站到那儿排整齐,然后123茄子才能拍,这个过程是不是特别累,特别麻烦啊,对吧,要等待的时间就特别长,对不对,那同样我们这里边要做这个检查,检查点算法也是,你如果就是说直接这里边告诉大家全停下来,所有任务都停,然后123茄子,那是不是这一个过程当中所有任务都不能干活啊,对吧,在整个你拍快。
20:10
拍照所有任务,每一个任务都得去拍快照,每个任务如果只要有一个还没完成这个状态,他们所有任务都都不能开始对吧,都得停着,所以这个过程其实对性能是非常损害是非常大的,那大家想一想,有没有更好的算法能够实现这样一个分布式的快照呢?各拍各的是吧?对,所以大家自然能够想到可以做这个各拍各的这样的一个操作,那他在什么时候去各拍各的呢?大家就自然会想到这可能需要得有一个。得有一个触发机制,对吧,我得知道大概在什么时候,或者说我收到一个什么标志的时候,就代表我现在应该去做快照了,对吧?啊,那这里边啊,这个flink对这个tpoint算法的一个实现呢,它主要是基于所谓的呃,那个昌吉兰伯特算法的一个分布式快照啊,这个当然它是还不是完全就是这个昌迪兰伯特算法啊,它做了一些改进,那它整个的一个思想其实就是。
21:23
就是大家所说的各做各的对吧,而且是把检查点的保存和数据处理是直接是分离开的,不需要暂停整个应用,只需要短暂的把每个任务自己做,这个陈浩的保存的时候短暂的停一下就可以了,不影响其他的任务。啊,那大家都会想,这个东西到底具体怎么来实现呢?当然我们就需要得有一个标记,告诉这个任务当前到底是是不是该做这个快照了,是不是该去存储状态了。那这个标记。就是这里要给大家介绍的所谓的检查点分界线checkpoint barrier啊,当然这个不同的地方,不同的文章可能翻译有所不同啊,有些可能管这个叫barrier,大家知道有那个篱笆的意思对吧?所以有的栅栏对,所以有有人可能把它翻译成这个检查点屏障啊,检查点栅栏啊,或者说检查点标记啊,呃,我个人觉得可能是分界线或者标记大家会觉得更舒服一点,对吧?呃,我我喜欢把它翻译成分界线,为什么翻译成分界线呢?其实就是因为它其实是flink里边的一种特殊的数据形式。
22:40
它的用途是干什么呢?一方面它的用途是告诉每一个算子,每一个任务,诶收到它的时候就可以开始做快照,对吧?这这是有这个标记的一个一个意思,另外一方面它是什么呢?它其实是可以把我们整条流上的所有数据直接分开了。
23:05
它分开的意思是什么呢?就是在我当前的这个barrier之前的所有数据,它属于上一个检查检查点保存的内容。而在我这个检这个barrier之后,所有的数据那就属于下一个检查检查点保存的内容了啊,所以大家想一想,这是不是就是一个标准的分界线,或者叫一个一个栅栏,或者说一个这个分隔符啊,对吧,就有点这个意思啊,所以说大家可以按自己的习惯把它叫做检查点标记或者说分界线,呃,或者什么都好吧,或者我们就直接叫他barrier就好。
我来说两句