00:00
前面我们已经介绍了flink当中检查点和保存点的概念,哎,那我们说所谓的检查点拆point,其实就是flink当中容错机制的核心,它就是保证了我们发生故障之后怎么样正确的恢复出之前的状态,就能保证流处理的状态一致性。这里就提到了一个状态一致性的概念,而且之前我们在介绍检查点的时候呢,还提到了所谓的精确一次的状态一致性exactly once,哎,那这又是指的什么东西呢?所以接下来我们就详细的展开去介绍一下状态一致性的概念,以及flink当中是怎样去保证精确一次状态一致。首先我们先来说一下什么叫做一致性啊,啊,其实一致性这个概念非常的重要,在分布式系统当中有这样一个概念啊,那我们更熟悉的可能是在事物transaction当中也有一致性这样一个特性,诶,那其实在flink当中,它的一致性呢,跟事物里边的这个表述可能会更加的接近一点,所谓的一致性简单来讲就是我们最终处理的结果。
01:11
得是对的,得是正确的,那对于分布式系统而言,因为我们知道啊,在处理的过程当中,每一步操作可能都有很多个并行的分区子任务。所以呢,呃,数据有可能处理的顺序就会发生变化,我们说就会出现乱序。而且如果说中间发生故障之后,我们从检查点checkpoint去做一个状态的恢复。是会退回到之前保存检查点的时候,某个数据处理完之后的那个状态,诶那如果说处理完这个数据之后啊,做了检查点保存,接下来处理的那些数据呢,有可能就被丢掉了,所以我们当时说啊,对于这个检查点恢复状态的时候还要要求source。任务所谓的原算子,这里还需要去能够去重置保存偏移量,能够去重新提交偏移量,那对于这个外部数据源呢,当然就还能够重置偏移量,能够保存之前的数据,重放数据,这样才能保证最后的结果不丢啊,所以如果整体来看的话啊,就是最后我们处理的结果就应该要像没有发生故障一样,该是多少还是多少,所有的数据。
02:28
不能丢,都要处理完,而且呢也不能重复处理,比方说我们窝是看的啊,你不能说重放数据之后,本来我们当前只有一个哈,哎,那接下来呢,一个哈,被统计了两次,后面我们统计的数量就相当于多加了一码啊,那所有的这些错误都不能出现,这就是所谓的一致性。那对于弗林格而言。故障恢复的核心其实就是要把之前的状态要计算对,能够恢复出正确的状态,所以我们一般情况呢,把它叫做状态的一致性。
03:02
所以我们可以根据刚才的这种基本概念的定义啊,会发现状态的一致性可以是有不同的保证级别的,哎,那什么意思呢?就是说你到底保证它的这个结果正确性保证到什么程度?那最好的情况当然就是说完全正确啊,一就是前面说的啊,一个数据都不丢都不漏,而且呢,也不会重复处理。这是我们想到的最佳的状态,这就是传说中的exactly one啊,精确一次,那在它之下呢,还有其他的更加宽松的,不那么严格的保证,比如说最基本的,其实叫做最多一次。At most ones。顾名思义指的就是说任务发生故障的时候,那我们从检查点去恢复状态,恢复之后继续正常处理数据,那整个的这个处理过程呢,因为这个故障的发生有可能会导致我们有些数据就被丢掉了,有可能就没有被处理啊,那至于说处理多少次,那他最多只会被处理一次,也有可能不被处理,被丢了当然就不会被处理了嘛,哎,所以如果我们做work统计的话,就是有可能他没统计进去啊,那如果统计的话,最多统计一次。
04:17
所以其实我们会发现这种所谓的最多一次状态一致性保证啊,其实就跟没有保证是一样的啊,因为如果说我们直接简单的重启什么都不干,就假如说根本不做什么检查点的保存啊,根本没有存盘故障发生了之后直接重启。然后就基于啊,我们的work直接全清零,然后基于新的数据直接开始继续统计就完了,那这相当于之前数据就全丢了嘛,它也能保证最多一次啊,那所以可以说这就是没有任何状态一致性的保证啊,相当于我们什么都没干嘛啊,这个看起来好像不太好啊,但是它其实也是一种状态一致性的级别啊,因为如果说我们对于当前处理的速度要求最高的话,实时性要求最强的话,而对于结果的准确性可能看的不那么重要的话,哎,那这也是比较好的一种方式,这相当于根本我们不需要做存盘处理吧,检查点这一步操作我们直接抛开了,要的就是最快速的数据处理。
05:18
啊,所以这其实还是一个权衡的过程,哎,那一般情况下我们会发现这个数据呢,还是不要这么什么都不做处理啊,还是要存盘一下,至少应该保证这个数据不要丢啊,这是底线,如果能做到这一点的话,这就是我们所说的达到了至少一次的状态一致性保证。At least once,顾名思义,它的意思就是说,当前我们的数据呢,至少会被处理一次,数据不会丢掉。哎,那也就是说呢,也有可能同一个数据被统计了多次。如果是work里边的话,就是首先我们统计出来的这个结果,所有数据不会少,统计出来的这个数肯定是有的啊,那对应的这个数据呢,有可能比之前的还要多一点。
06:05
被重复统计了。这种状态一致性的级别在什么场景下有用呢?诶,我们可以思考一些具体的需求啊,比如说我们统计这个电商网站的UV值。因为我们知道它是独立访客数,所以对于同一个用户的数据。对于UV的影响,其实只会生效一次啊,也就是说我们每一个用户的那个访问数据啊,同一个数据,如果说我们计算两次,处理两次的话,最后在UV里边的体现最多只会生效一次。啊,因为相同的用户,这个数据相当于就被滤掉了嘛,所以这种场景下,我们就说这种操作是具有幂等性的啊,幂等性我们知道就是相当于做一个乘方操作,乘完了之后还是自己啊,这就是幂等,就是做多少次最后的效果跟只做一次操作是完全一样的,那在这种场景下统计UV,很显然只要达到至少一次的状态一致性,保证数据不丢,我们统计出来的就是正确的。
07:08
偏高,那当然了,有一些场景其实就会出现偏差,比如说如果统计的是UV的话,那就是每一个用户他的访问的这个频次访问的数据啊,统计一次我们就加一,如果多统计一次,重复数据来了,多统计一次,那就又加一,那这样的话就会导致最终的结果不一致。所以具体的使用的话,还是要看我们应用的场景啊,有些时候使用至少一次的状态一致性,保证完全可以满足我们的需求。啊,那在具体使用的过程当中呢,我们会发现它要求至少不丢数据,这就要求如果发生故障,我们进行恢复的时候,之前的一些数据需要能够重放,哎,所以我们说。首先需要flink里边的原算子SS任务,把读取的偏移量作为状态写入检查点,另外呢,还能够向外部的数据源去重新提交偏移量啊,那重放之前的数据,这样的话才能实现数据不丢,那我们知道卡夫卡诶,就能做到这一点,所以弗林格跟卡夫卡的连接也是非常的频繁啊,这是一种经典的架构。
08:17
哎,那最后我们说啊,真正最完美的情况是什么呢?那就是数据不光不丢,而且也不会被重复处理。数据会被处理一次,而且只会被处理一次,这就是所谓的精确一次exactly one。在这种状态一致性语义下,我们处理的结果可以说是保证完全正确啊,这就跟应用的场景没关系了啊,你统计UV也好,PV也好,无所谓,最后绝对是正确的。那我们知道你如果想要做到精确一次的话,首先你得先达到至少一次,首先数据不能丢嘛,所以之前至少一次要求的这个数据源那边啊,可以重置偏移量,可以重放数据,这个要求现在同样还是生效,还得要求数据源可以重放。
09:05
那另外还需要做到什么呢?那其实我们知道在flink内部啊,有检查点checkpoint的这样一个机制,它的底层就保证了。进行分布式快照保存的时候,我们保存的总是处理完同一个数据之后的所有任务的状态,哎,那这个时候如果说我们保存了这个,那后边所有的数据呢?诶,那就那就去重放吧,然后根据我们之前所说的这个检查点的算法就会发现啊恢复之后,那就是完完整整的恢复到了保存检查点那一时刻的状态,那接下来呢,我们就重新提交偏移量去重放数据,继续处理,整个的这个过程就像没有发生故障是一样的。这就是我们所说的状态一致性的级别啊。当然了,我们最希望达到的就是精确一次的状态一致性保证。
我来说两句