00:00
接下来我们来讲flink里边的状态一致性啊,那这一部分呢,分成这么几呃,几大块吧,首先我们说一下明确的定义一下什么叫状态一致性,然后呢,再还得再给大家复习一下,说一下这个checkpoint的一致性检查点,接下来呢,我们专门要强调一下端到端的状态一致性,And to end的状态一致性到底是什么意思?呃,然后接下来我们主要是说要保证端到端的所谓的精确一次exactly once的状态一致性保证,最后给大家专门的强调一下flink和卡夫卡他们连接起来这样一套系统是怎么样去保证端到端的状态一致性的。啊,所以这是这一部分内容啊,好,首先我们看一看什么是状态一致性啊,其实大家知道,对于这个流处理器内部来说啊,所谓的状态一致性其实就是平常我们所说的,不管出现什么情况,不管中间出现故障再恢复还是怎么样,对吧?呃,无论怎么样,最后你计算的结果要对,要准确啊,这其实就是所谓的内部的状态一致性啊那。
01:16
大家可能知道就是我们既然是状态一致性嘛,那其实就是说对于零处理而言,是不是就是中间保存的这些这些状态对吧,每个算子任务他们自己的那个状态。保存的时候和恢复的时候,一定他们都是要一致的,言下之意就是一定要是在要不都处处理完某一个数据,要不都是没处理某一个数据的那个状态,对不对啊,那这里边我们的期望是一条数据,他既不应该丢,也不应该重复被计算,对不对啊,所以如果在遇到故障的时候呢,应该能把状态恢复出来,恢复之后的重新的那些计算结果应该是。
02:01
跟没有出现故障,正常运行的过程当中得到结果应该完全一样,对吧?啊,所以这其实就是我们想要的这个所谓的状态一致性啊,那比方说大家还是看这个图,我们之前也已经看到了啊,所谓的状态一致性就是什么呢?就是如果现在读到七这个数字的时候,然后下边这一个奇数求和的这一部分给挂了。如果我们恢复状态的话,是不是SS这里如果要恢这个恢复到七的话,是不是相当于就有问题啊。因为S这里恢复到七,相当于七已经读进来了,但是下面这里的这个状态,九显然是还没有加上七的状态,对不对啊,那这个时候你如果没有存数据,只存的状态的话,这显然状态就不对了,后面你如果继续加的话,七这个数字就丢掉啊,所以这是这样一个呃,一个状态啊,那大家可能还会想到,那如果说你要是这个,呃,假如说啊,就是到到这里我们是回复到六的那个状态,是要把六再重新放一遍,但是我们还用这里的这个12的这个状态可以吗?
03:12
因为这个12的状态是不是六已经加过了呀,你如果要是这里用12的状态,然后接下来再把六重放一遍,那显然它是不是就加了两次,呃,所以这里边就这两种情况都不能接受啊,呃,这里大家要要注意啊,我们所谓的保证应用程序内部的状态一致性。并不是保证应用程序输出结果的一致性,我们所说的内部,就是说内部计算处理过程当中的这些状态是一致的,对不对啊,如果说你后面要跟了那个think系统的话,那这个就很难办了,对不对?一旦要是已经think到外面,那这个显然就呃,你保证它不丢,可能还好说,你要想保证它只写一次,就是不能重复计算,这个可能就相对来讲麻烦一点啊,所以这个我们是需要去分别去讨论的。好接下来大家看一下这个所谓的状态一致性的分类,或者说不同的级别啊,状态一致性有不同的级别,首先是所谓的at most ones at most ones,这个翻译过来,字面翻译过来叫至多一次,最多一次,对吧?啊,最多一次的意思是什么呢?
04:31
啊,那其实就是说当故这个任务发生故障的时候,我啥事儿都不干对吧,既不恢复丢失的状态,也不重放这个丢失的数据,那那这种情况,这就相当于是什么呀,一旦发生故障,是不是数据就有可能丢,但是不发生故障,那就有可能没事儿,对不对啊,所以就是说最多这个数据处理一次,没准儿有可能就丢了,那那大家想这个最多处理一次,这个其实是代表什么呀,换句话说,其实这就是没什么保障的意思,对不对,相当于你什么都不干,它也它也是这个状态嘛,啊所以这其实就是根本没有保障的一个含义,那听起来这个好像是挺差劲的,一个一个一个东西啊,为什么这还专门把它当做一个状态一致性的级别拿出来说呢?
05:23
对,大家会想到你什么都不干,直接对吧,来了数据直接处理,然后这个故障之后也不管,那是不是这个过程就效率非常高啊,实时性可以做到最好对不对啊,是一种性能不会受到任何的影响啊,所以它相当于就是牺牲了我们的容错性,牺牲了正确性,一致性,来保证了更高的性能,更好的延迟,对吧,更小的延迟,所所以这是这个at most once,但是在大多数真实的场景下面啊。我们我们肯定会觉得这个你这个什么保证都没有对吧,来了之后数据都有可能直接就丢没了,这显然是不靠谱的一件事情,所以往往我们至少是希望,呃,你重复不重复这个我先不管,你至少不要把数据给我丢了,对吧?因为你如果重复了的话,我只要有数据,我可能还能再去做补救,那你一旦数据丢了,我真的是一点办法都没有了,所以这就引出了下一个一致性级别,就是所谓的at least once,就是所谓的至少一次,那至少一次的意思就是。
06:33
啊,就是这个数据至少会被我处理一次,我保证它肯定不丢对吧?呃,所以它前提是保证了数据不会丢啊,但是这个数据有可能被处理很多次,对,会被处理,重复处理啊,这是at least的一个一个状态啊。呃,那大家会想到如果要想保证这样的at least once的话,呃,大家想到我们还需要什么样的东西呢?
07:02
要想保证就是这个数据不丢,怎么样就能严格保证这个数据不丢,可以置到,就是有有些同学已经想到了,就是原任务那里边可以去重置数据源的偏移量,对吧?那它可以重置偏移量的话,其实代表的是圆那边把偏移量重置,它其实是不是把之前的数据得都存下来啊,对吧?啊,如果它那边数据都已经丢了,你这边再重置偏移量都没用,对不对啊,所以它是得支持这套系统,所以说如果我们不考虑这个圆那里的问题,我们直接考虑到整个所有的任务里边去的话,如果想要保证不丢数据。那其实大家会想到你是不是相当于就是要不就是把数据全存下来,对吧,你不管是存在哪儿吧,是圆那边全存下来也好,还是说我们中间某一个数据,某一个任务,把数据到这儿的数据全存下来也好,这是不是一种方法啊,对吧?啊,只要是来的数据我都存下来,那肯定保证它丢不了,一旦发生发生故障,我这相当于是写了一个log,对不对,对吧,把这个数据当成log写进去了,发生故障的时候,我可以从log里面去恢复,那另外还有一种一种实现想法是什么呢?那就是用这个所谓的结果确认机制。
08:29
就是说只要我这个数据啊,就是正常情况下,我这个数据都是先保存在缓存里边的,直到这个数据被所有的任务都处理完成之后,然后我再真正的这个确认对吧,真正的在提交,所以这就相当于是这样的一个处理过程,这其实有一点像这个所谓的事务性提交对不对啊,所以这其实大家看到啊,就是在这个一致性的这个分析里边,这其实就是最主要的两种思路啊,其实就是一种是写写log,写日志,另外一种就是事务性提交。
09:05
好,呃,那大家会想到有没有比这个at least one更强大更给力的这个一致性语义呢?啊,当然有,这就是我们已经听过很多次的所谓精确一次exactly ones,那所谓的exactly ones,那就是。就是恰好一次精确一次处理这个数据,不仅仅数据不能丢,而且不能重复处理,对吧?啊,就是我刚好就处理了一次,针对每一个数据内部的状态,只仅仅更新一次啊,这个要求就会更高一些。这里边其实要跟大家说的就是说flink里边能够做到什么样级别的状态一致性保证呢?他能够做到。那是他,他是靠什么样的机制来保证这样的exactly one的呢?哎,就是我们前面给大家讲过的checkpoint。
10:03
当然这个它其实是使用了一种轻量级的快照机制,对吧,保证了我们在同一个所谓的这个时间点,这个时间点是同时处理完同一个数据之后的那个状态,对吧?然后把所有任务的状态做快照保存下来,然后出现故障的时候呢,我就可以从之前保存的checkpoint里边把它恢复出来,那在内部的状态看来是不是跟发生故障以前做完那个checkpoint的那一时刻是不是完全一样啊,对吧?所有的状态完全一样,呃,那个我们看到的所有数据其实真的是就是处理一次,而且是只处理一次,那有同学说,诶不对呀,你中间有些数据不是要重放的吗?有些数据明明就是被被被处理了两次啊。诶,这里大家要注意,在flink内部里边,我们并没有保存数据对吧,所以flink内部的状态是不是它只有自己的一个状态,所以他根本不知道自己处理了多次啊。
11:08
对吧,所以从这个意义上讲,其实。只要有checkpoint flink内部就已经保证了精确意思这样的一个语义,好,呃,那啊这里边就是给给大家提到了这个checkpoint啊,我们还是来看一下,这就是呃,这个应用状态能保证它这个故障恢复和保证1EXACTLY once语义的一个核心啊,这就是检查点机制,有状态流应用的一致性,检查点其实就是所有任务在某个时间点的一份快照,对吧?啊这个就是之前给大家强调过的这个概念。呃,当然这个图我们之前也已经看到过了啊,大家知道是怎么样去保存这个数据呢?S任务这里边五这个数据已经读进来了之后,那SS这里边的偏移量就是五对不对?哎,如果这这个时候要触发这个拆框的操作的话,那它就把五这个偏移量当做状态存到状态后端里边去。
12:12
那同样后边的所有任务是不是也必须得处理完五那个数之后,把那个状态存到状态后端啊,然后再恢复的时候就能恢复到跟他完全一样,五已经处理完,然后后边六期都没处理的这个状态,对不对啊,这就是所谓的exactly one。呃,那大家会想到这个其实好像还不是特别的给力,为什么呢?因为在实际应用当中,我们其实并不只是在flink内部,你处理的过程当中要保证exactly one要保证正确,对吧?我们往往要求是什么呢?是整个应用处理场景里边,从源那边读数据开始对吧?从读呃,读进来消费数据,到一直到最后think写写到外部系统里边,整个这个流程应该都是要正确的,这个正确就就。
13:08
如果要是要求exactly one的话,那就得至少不丢数据,而且还不能重复处理数据,对不对啊,这就包括了你前面S那里边能够重放数据,能够保存所有的这个数据,能够重置偏移量,而下边的SK那边是不是还不能重复的写啊?对吧,要不然你一旦是写进去之后,那就有可能被别人消费掉了,或者说已经被别人读取那个状态了,那那让别人看到的这个状态显然就不一致了,对不对?哎,所以在这种情形下,我们一般要考虑的就是从头到尾整个完整的处理流程的一个一致性,这种一致性就叫做端到端的状态一致性,所谓的按图案对吧。在这个过程中,如果你想保证端到端的状态一致性的话,那是不是就得保证整个处理流程里边每一个环节,一个组件,他们都得保证状态一致啊,对吧?那大家想一想,在这个过程当中,假如我flink内部已经启用了checkpoint了,我们说可以达到exactly one,对吧?能达到这种级别的状态一致性保证,但是外部系统保证不了exactly one保证不了不重复写,那大家想整个这个系统这叫exactly one吗?
14:29
不叫对,所以整个端到端的一致性,一致性级别取决于的是。整个对组建里边最弱最差的那个环节,这还是木桶理论对吧,所以大家看这个其实思路是呃,贯穿始终的啊,就是这样的一个状态。
我来说两句