00:00
我已经知道了状态一致性的概念,那接下来我们就来考察一下flink里边到底怎么来保证我们结果的状态一致性呢?哎,这个其实之前我们也已经说过了啊,主要它就是靠checkpoint来保证,Checkpoint是一种轻量级的快照机制,之前我们也已经讲到过了啊,它其实就是对当前所有任务处理完同一个数据之后的状态做一个快照保存,哎,那它的含义是什么呢?其实就是说等到出现故障,我从这个状态要恢复的时候呢,就刚好会恢复到当时处理完同一份数据之后的那个状态,所以接下来诶,你前面再去重放数据的时候,当然就能保证,只要呃,前面我们这个数据是可重放的,对吧?是是有还有这个数据的,那后边就会保证,诶,它总是会接着之前我们已经存盘的那个状态点在后面再去往后叠加,对吧,处理只处理一次。
01:00
那大家要需要注意的是,这里所说的只处理一次,并不是这个操作,就像我们前面说的那个偶数奇数求和,并不是说这个加的这个操作只做一次,而是说我们最后的那个状态里边只加了一次啊,那呃,所谓的这一个呃,一致性检查点,这其实就是我们flink内部保证状态一致性和故障恢复的整个机制的一个核心了啊,大家可以再看一下这个图,我们在整体的恢复一呃回忆一下啊,当时我们就说过要保存的时候保存什么状态呢?就是全部数据,哎,那都是处理完五这个数据之后的状态,所以前面S任务这里边保存的是一个偏移量啊,S5把这个保存起来,后边这个some even和some odd的奇偶数求和分别保存的也都是处理完五之后的状态,这里边偶数求和二和四是六对吧,加起来是六,那奇数求和呢?135加起来是九,所以必须是。
02:00
存这样一个状态之后,如果挂了的话,那后边就是假如说啊,后面做这个六和七,大家还记得在七的时候挂了,那怎么办呢?六和七就全部都要重放,我恢复状态的时候恢复的是569这样的状态,对吧,都处理完五之后的这个状态,所以接下来六和七哎,同时再再去做这个重放就可以了,能保证这里面的这个叠加结果只处理一次。啊,那当然了,现在这个我们可以有这个区域的,呃,重启的这个策略,那就可以怎么样呢?就是相当于我前面的这个状态,假如说已经处理到这个六和七之后了,那这里边就相当于这个even,这里边的这个状态可以不变,对吧?我继续往后处理,我只是把这个奇数的这个状态从之前五的那个状态把它恢复出来,从差你把它恢复出来,那呃,大家就会想到前面就相当于我要求它还得重放一个什么数呢?得重放这个六和七的数据,要要给我这个分支来去重新做传输,对吧?而我上面这个分支就不需要去重放这个数据了啊,这是这个现在做的一个一个小的优化啊,啊,那对于我们理解原理来讲,大家就是理解这个重放数据,然后这里边保持状态一致性就可以了。
03:21
那所以我们说,呃,接下来我们要考虑的就是一个端到端的状态一致性了,那这个又是一个什么概念呢?前面我们提到这个保持这个状态一致性,这只是保持了什么呢?Flink内部状态处理结果的一个状态一致性,对吧?啊然后在这个过程当中,我们还想到了他必须有一个前提要求,必须是我这里边是不是任务从这个数据源这里要可以重置这个偏移量啊,哎,大家想我们这里边就相当于想的这个数据源,那就肯定就是像卡夫卡这样的数据源了,对吧?诶这里边是一个消息对立,大容量消息对立,我们可以把这个数据都缓存在里边,对吧,前面做一个这个缓冲,做一个蓄水池啊,那你你这里边当然就可以做这个偏移量的提交,那假如说我们这里边你你就像我们之前那个啊,Soet文本流直接从socket文本流里边去读数,它那边能重置偏移量吗?当然没有啊,它没有存储啊。
04:21
对吧,它就是实时的有一个数直接传递到我们当前的这个端口上来啊,那这里边你当时监听收到就收到,收不到就丢了,那怎么办呢?那就最终即使我们内部有checkpoint也保证不了最终的状态一致性,对吧,你相当于还是要丢啊,啊这首先这是这个输入源,这边另外大家还想到了,那假如说你这是输入源嘛,后边我们完整的操作是不是后边还应该有think任务啊。对吧,Think任务这个还麻烦一点,就是他还会往外部系统去写入啊,啊,那假如说我们这里面的这个数据,你得到的这个计算结果,你在这里边这个本地的这个状态只加了一次H是六,然后后面如果又加了六,呃,加成了12,呃,你你说我之之后恢复的话,要恢复到六,那就相当于这个六就没加上,这个是没问题的,那假如说我外部系统已经把那个12输出了一遍的,那怎么办呢?那后边你再恢复之后,我再重新加,又加成了12,再输出一遍,那不相当于输出了两次吗?啊,所以大家要注意啊,如果我能考虑到整个这个应用程序的话,那可能你不仅仅考虑flink内部的状态。
05:35
这个状态是对了,有拆point就对了,但是呢,呃,还得考虑source,就是我们的数据源和think输出到外部系统里边,这个过程当中到底能不能保证就是处理一次,而且只处理一次,对吧?Because once,所以这里面我们就提出了一个概念,叫做端到端and to end的状态一致性。
06:00
所以说呃,就是端到端的状态一致性就意味着什么呢?就是我们保证它的这个结果正确性呢,要贯穿整个流处理应用的始终,对吧?从头到尾要要保证它是对的,也就是从一开始我们这个呃,读取数据,消费数据,到最后写入到外部系统去,去真正的让有这个应用的展示,或者说一个存储都要保证它是一致的,那那这里边整体来讲,这个状态一致性的级别由什么来决定呢?哎,这里边就有不同的环节了,有中间flink处理的环节,有前面south这一部分的环节,对吧,还有后边think部分的环节,那我们知道既然是连接成的整套的系统,那整整体系统的状态一致性级别是不是它就应该取决于还是木桶原理嘛,取决于那个最短的短板对吧,所以取决于所有组件中一致性最弱的那个组件。
07:00
哦,那那现在我们的这个问题就来了,如果说我想要达到最高级别的exactly once的状态一致性保证的话,那应该怎么去做保证呢?三个组件三个部分都必须达到一个啊,那首先内部这个比较简单,拆point搞定了,那如果要是S端怎么办呢?S端其实不涉及到我们所说的这一个,呃,就是就是只处理一次的问题,对吧?就只要他能重放数据,只要数据不丢,大家想你这个就是因为它不涉及到我们外部写入嘛,你哪怕是读取多次,其实对我们最终的影响,最终的结果没有影响,对吧?呃,对后续的这个操作你应该是由这个think那边去控制的,而不是由south控制,所以S这边呢,我们要求就是必须要可以重设数据的读取位置,也就是可以重新提交偏移量,Offset,就是我们的数据源那边,他必须得把之前的数据都能缓存下来,而且能够给我们保存着它的偏移量,能够重置啊,那另外还有就是thinkink了,Thinkin端的话,哎,如果说我们想要去做这个故障恢复的时候,不要让它。
08:14
啊,诶,这里边就是端已经给我们保证数据不丢了,对吧?哎,那think端这里边至少你数据不丢嘛,至少能保证了,那这个时候怎么样能保证这个数据不会重复写入呢?所以我们重点是考察这个问题,这里就有两种实现方式,一种是密等写入,另外一种是事物写入,这就是我们端到端要保证exactly once的这样的一个考量。
我来说两句