00:00
接下来我们要基于之前讲过的时间语义,给大家再往深里边讲一讲flink给我们提供的特性,这就要考虑什么,要考虑前面说的乱序数据了,因为之前大家想就是我们做这个处理的过程当中,既然考虑到有不同时间语义,有事件时间和处理时间的不同,那就会涉及到一个问题,就是说诶,你前面这个发生的事件,有可能等到进入弗link系统之后,我们在处理的时候,有可能它落到后边了,对吧?啊,就是有可能本来应该是08:59产生的数据,等到我们在处理的过程当中,他有可能就等到09:01,这个机器时间09:01的时候,我才接收到这个数据啊,那你说这个这个数据我到底是前面我那个窗口到九点了,八点到九点的窗口到底是关还是不关呢?哎,这里面大家可能有一个非常简单的想法,就是,哎,那这个很简单呀,那那就不关我,我再多等一会儿嘛,但是大家注意啊,如果说你的这个思想就相当于是什么呢?就相当于我现在还用的是处理时间对吧,用的还是这个processing,那你可以这么干,就是我再多等上一分钟,就多等上两分钟,然后再关这个窗口,但是这里面就有一个问题,你怎么去判断当前我到底应该等多久呢?哎,你说我拍脑袋想一个等一分钟,等两分钟,这个具体的这个数据它的延迟未必是这么长时间呀,而且这个还有一个更大的问题是,你直接上线运行之后,你说这个数据它的这个时间真的就一直是一直就是延迟一分钟,就就永远都是延迟一分钟过来吗?
01:41
那说不定有段时间它这个延迟就短了,对吧,当前这个网络环境好了之后,它这个延迟一秒钟就来了,那你还要等一分钟,你是不是这个性能浪费就比较大啊,那那另外有些时候可能这个网络状况就特别的差,你如果要是说还是按照一分钟去等的话,这个数据根本就收不进来,大部分数据都到五分钟以后才来啊,当然这有点有点夸张啊,一般我们网络状况不会那么差,对吧?啊,这个就是按分钟来记,这个太夸张了,一般按秒来记这个,呃,按秒级别的延迟,这个网络环境其实已经是比较差了啊,那所以呃,这只是给大家举例啊啊,那那你说你如果要是说这个数据它都已经延迟到那种程度了,你还是很死板的定死了,就就等一分钟,那那这就完全完全等不来数嘛,对吧,就要不就是说这个你延迟白白的浪费了这个等待的时间,呃,时效性我们的这个实时性就就差了,要不就是说呃,你等的话还还等不来,你等了最后还是一个错误的结果,对吧,还等不到,所以。
02:41
和正确的数据到达,那所以这里边我们的一个想法就是你不要用,不要再去想用这个processing time处理时间等待的这种方式去等到所有数据了,那我们用什么呢?哎,我们可以用事件时间嘛,哎,大家知道事件时间主要是用什么来表示呢?那就是数据本身带着的那个时间戳,所以现在我就可以怎么样呢?就是你数据,比方说哎,这个08:59的数据来了,那我就认为现在时间不就到08:59了吗?对吧,九点钟的数据来了,就带着九点钟时间戳的那个数据来了,我就认为现在我的时间到九点钟了,至于我现在本身系统当前是呃,这个09:05还是09:10,对吧,到底过了延迟了多久,这个并不重要,我只考虑现在的数据,它的那个时间戳进展到什么程度了啊,所以接下来我们一个非常直观非常简单的思想,就是我要用。
03:42
事件时间,也就是从数据里边提取出来的那个它发生的时间戳,作为当前时间推进的一个考量啊,那那所以接下来我们的时间就相当于变成这个时间戳来控制了,对吧?就跟系统时间没关系了,大家先把这个概念先转变过来,哎,那这样的话我们就解决问题了吗?其实没有解决问题,这还有一个问题就是乱序数据,哎,那首先我们来看一下啊,在理想的情况下,我们要用这个数据自己带着的时间出来,表示当前的系统时,表示当前的事件时间,对吧?当前我们要做处理的这个时间啊,那最好的情况是什么呢?就是数据就按照它的这个产生的顺序一个一个来啊,然后你看,呃,就是我们这里的顺序,就是从左到右一个一个数据来对吧,在这里边第一个数据来的时候,这里边这个数字表示是它的时间戳,那大家看到一啊,我我我们时间戳本来应该是毫秒数,我们这里面就认为。
04:42
是秒吧,对吧?啊,稍微容易理解一点,第一秒的数据先来了,那我接收到这个数据,我就认为当前的时间是一对吧?呃,当前的这个时间就是一了,你一秒钟,假如说一秒有要关的窗口,那我就关嘛,对吧,因为时间时间已经到一了,呃,所以之前的这个,呃,该到的点该到点,该做的这个操作当然就该做了,那后面呢,来了二,那我就认为现在时间到二了,对吧,两秒钟的窗口该关可以关了啊,那同样就是你后面每来一个数据,我就根据它的时间戳更新当前的时间,这样的话,我们的时间就可以不停的朝后推移,对吧?只不过现在的推移不是系统本身有一个时钟在那儿推移,而是按照接收到的数据,它的时间戳变大,来推移我们当前的时间啊,那就是比方说我有一个五秒钟的窗口啊,那大家想到是不是就直接等到这个五秒的时间,这个五秒的数据来了的时候,这个时候我。
05:42
就可以把五秒钟的窗口关闭了啊,那这个时候12345是不是都到齐了,我就把这五个数全收进来了,对吧?那这样做一个这个窗口关闭,那后边如果你再来数的话,五秒之前的数就不会来了嘛,后面再来就是六秒的数据了,它也不属于这个窗口了啊,所以这个就结果完全正确,但是这是非常理想的状况啊,现实往往不尽如人意呀,啊大家看看就是我们说的,因为有这个分布式系统的这个存在,大家知道在不停的传输的过程当中,先发生的数据,它到后边处理的时候未必是排在前面的,这就有可能出现什么情况呢?哎,我们这来了的数据变成这样了,大家看145236,如果这样排列进来的数据,我们一个任务接收到他的时候,你认为当前的这个系统时间应该是多少呢?
06:33
按照我们的规则,一来了之后,诶,那现在系统时间是一对吧,那四来了之后,系统时间变成四了,已经四秒了对吧?五来了之系统时间已经是五秒了啊,那有同学说,那二来了之后,难道系统时间再跳回到二吗?那肯定不会对吧?我们的时间当然是就是沿着一个方向朝后朝后推移的时间不能跳转啊,青春不能再来对吧?啊,所以这个过程肯定是不能不可逆的,所以这里面就有一个问题了,我现在要关闭五秒钟的窗口,五秒钟有一个窗口的话,零到五秒对吧?嗯,那这个窗口是五,这个数据来了之后我就应该关了吗?大家想想是应该就关了吗?
07:16
这是一个问题了,我们当然可以关,对吧?按照这种方式,五来了之后,我直接就关,得到的效果是什么呢?收到的数据零到五秒的数据是1453个数据。但是。但是大家发现后边可能二和三才姗姗来迟,这个时候相当于这两个数据他来的时候窗口都已经关了,对吧,计算都已经输出了,这个数据是不是就丢了呀?啊,所以这里边就会出现数据的丢失情况啊,那当然有的同学可能想到了,有一种解决方案是什么呢?诶之前我们讲那个window API的时候,不是有一个允许处理迟到数据嘛啊,对吧?啊,就是每一个数据,呃,每一个窗口关闭的时候,我可以再给他延长一段时间啊,这段时间我可以继续等后面的这个数据啊,这是一种处理方式,后面我们会统一给大家讲啊,这确实是flink里边处理乱序迟到数据,这个不算乱序数据啊,处理迟到数据的一种手段,但是我们这里边又会想到,就是你如果说总是所有的这个窗口,让他多等一段时间去处理这个的话,一方面哎,我们这个,呃,就是本身窗口的这个状态不能释放,对吧,一直得等。
08:29
哎,这这是一方面这个影响,另外一方面就是说我们实际的这个场景里边可能是什么呢?诶可能这个这里边如果是秒的话,这个还还算延迟比较大了,对吧?更常见的情况是什么呢?是大量的,就是这种乱序的数据来了之后,他们相差可能就那么几毫秒,几十毫秒,然后就是很短的这个乱序的程度,你这个时候如果窗口直接等你等上一分钟,那是全能收进来,对吧?但是好像就没有这个必要,对不对,那在这这种情况下,我其实应该是整体这个时间给推移,大家想想是不是就相当于整体时间往后推移一下,就可以把这个乱序的数据全能处理了呢?
09:13
啊,所以接下来给大家提出一个处理的方式,那是什么呢?那就是我可以引入一个整体的时间的延迟机制,就当前我判断这个系统的这个事件时间,对吧?系之前我的判断方式是来了什么时间戳的时间,我就认为这个时间到了,到了哪里了,而现在我呢,我不要直接这么来做,我相当于是要让这个时间滞后一点,稍微的迟一点,言下之意就是什么呢?五秒的这个时间出来了,我现在的时间不要认为它已经进行到五秒钟了,比方说我可以认为它只进行到现在的时间,只进行到两秒钟。如果说现在时间只进行到两秒钟的话,那意思是什么呢?就是两秒钟之前的数据该到的都到齐了啊,如果有两秒钟的窗口你该关可以关了,但是呢啊,三秒四秒的数据还有可能来,对吧,那现在你不要关五秒钟的窗口,五秒钟窗口没到点呢,现在时间只只到了二,然后这样的话,我是不是后面就可以二三来了之后可以继续处理了啊,所以这个其实就相当于是给我们整个的时间引入了一个延迟机制,这个延迟机制。
10:32
大家会看到啊,就是说这个乱序数据会让这个窗口计算结果不准确,对吧?为了让它能够更准确的计算,那么我们就要引入一个延迟机制,这个延迟机制就叫做water mark,在flink的系统设计里边就叫做water mark啊,它的字面翻译有时候会翻译成水位线,有时候会翻译成水印,不管怎么样,大家记得它是一个mark mark就是一个标记嘛,对吧?啊,那这个标记它主要是指是什么呢?它就是用来指示当前的事件时间。
11:05
啊,所以大家注意啊,这里边有一个概念,就是说这这是说什么呢?是watermark是一种衡量even time进展的机制,它用来可以干什么呢?可以设定一个延迟触发,就是相当于我们的那个事件时间已经来了,对吧,这个数据的那个事件时间时间戳已经来了,但是呢,我要让他在这个基础上延迟一段时间,再去触发相关的那个,比方说窗口关闭的操作,或者说我们想做的一些跟时间相关的操作。这个这个含义,它其实底层来讲就是把我们整个的时间全变慢了一点啊,啊所以说这个有一个类比,就是说什么呢?就是像这个赶车对吧?啊,大家看你这每一个窗口,你说八点到九点,九点到十点,对吧,就相当于我们那个班车一样,比方说一个班车,这个班车就是九点发,然后下一个班车是十点发,那这种情况下,我们赶这个班车的时候,往往会出现什么情况呢?哎呀,要等的人迟到了对吧?哎,本来要坐这个班车,但是呢,姗姗来迟,路上堵车了赶不上,那怎么办呢?啊,如果说是大家这个我们一个班的同学,大家包包一个车出去这个春游秋游的话,那肯定我们是要等一下的,对吧?哎,所以一般情况我们的做法是什么呢?就是直接等待对吧,比方说我我我等待呃一个时间,呃等等个十分钟,然后把该来的是人,来的人,延迟的人都都等到。这种操作方式有点像什。
12:36
呢,就有点像我们之前说的processing time那个前提下,我直接在那等着,对吧?Processing time处理时间我设置的是九点就还是九点,但是呢,我给你等上一分钟,等上十分钟,这是这种方式,那我们现在waterma的这个机制是什么呢?哎,这是相当于我直接就告诉司机师傅,哎,我们现在的这个时间,这个事件时间,你现在本身就没有表,对吧?因为你如果有表的话,这就相当于有processing time了嘛,我们现在这个时间按照按照这个按照什么来判断呢?我们就按照每一个人来的时候,他自己带着的那个时间戳来判断,对吧?啊,那那就是,然后接下来我们就是什么呢?就是每一个人来的时候身上带着一个时,就是他自己要赶的那一班车的,呃,就是类似这样的一个时间戳,对吧,大家可以认为这样,所以呢,我我等就是来的时候上我这班车的,当然带着时间戳就都应该是呃这个。
13:36
九点钟这班车对吧,九点钟这个时间,但是我这些人来了之后呢,我不认为当前的时间已经到九点钟了,我怎么样呢,我多等一会儿,我要等到。要上09:10那班车的人他们来的时候,我才发九点钟的这个这趟车,诶大家想想是不是这样一个等待的机制啊,对吧?啊就这样等待,我认为下一班赶下一班车的人啊,这个都已经来了,那我认为你你上一班车再堵车对吧,你这个十分钟我应该已经把你等进来了啊,所以说这个时候我就直接发车不等了,所以这其实这样的一个延迟机制,他也可以认为是一个延迟发车的机制,对吧?但是跟我们想的那样,我就直接坐这儿等,这还是不太一样的,或者大家可以用另外一种方式来理解,就是什么呢?就是司机师傅他是有个表的,但是这个表呢,我们现在让他统一调慢,就waterma的含义是什么呢?它的这个延迟指的是直接把表就调慢了,也就是说司机师傅那边看的时候还是九点钟准时发车,但是呢,诶我们因为有这个乱序的数据,我直接提前偷偷就把他的这个时间给他。
14:49
拨慢了十分钟,那大家想他看着表去准时九点发车的时候,是不是相当于我就等了十分钟啊,对吧,就有点像这个哈,那为什么我能把它这个表播慢呢?就是因为我引入了一个water mark,这个water是我们现在的时间,而这个water mark它的机制是什么呢?就应该是比哎当前可能最大的那个时间戳,我要比它调慢一点,对吧,比当前的这个时间要调慢一点,因为大家想到我如果已经接收到五秒的数据了,那其实事件发生当前肯定已经到五秒以后了,对吧?如果不考虑我这个传输延迟的话,那肯定时间已经到五秒以后了,所以这个时候你其实如果把它调慢的话,就是一个延迟等待的过程。
15:36
好,这是关于这个watermark的概念啊,然后这里边给大家说再说一下这个一些具体的概念,就是说那个watermark,我们我们发现遇到这样一个water之后,它主要是用来表示什么呢?它主要是用来表示,如果说我们看到一个water,它是个标记嘛,一个water它它是五对吧?它表示什么呢?它表示当前的事件时间是五,然后也就表示五秒之前,就是他时间戳小于这个数的所有的数据都已经到达了。
16:10
那言下之意就是说,假如你有五秒的窗口结束时间是五秒的窗口,对吧,那你就可以关闭了,所以大家看到这个看如音斗啊,时间窗口的关闭操作都是由water mark去触发的,哎,所以现在就是说我们已经不用这个本身数据自己带着的那个呃,时间戳去出发我们的窗口操作了,而是用watermark来出发这个watermark的这个有有同学可能就想到,那你这个watermark这相当于什么?不就是还是引入了一个延迟,然后来保证我们最后的结果正确吗?啊,确实是的,这就像我们之前讲的这个luda架构,大家还记得吗?流处理发展变化的过程当中,第二代架构怎么做的,为了要解决结果正确性,处理乱序数据的这个问题,它是怎么做的呢?啊,为了还要平衡快速性,对吧,它就是很快的先输出一个近似正确的结果,用一个实时的流处理系统输出一个快速的正确的近似正确的结果。
17:10
然后呢,呃,再去用一套批处理系统,然后我攒这个数据等待,对吧,等所有数据都到齐了之后,然后我输出一个最终准确的结果,最后再结合起来,而我们现在watermark这个机制,这就相当于什么呢?我可以去让程序自己来平衡,你到底是要快还是要最后结果正确啊,就是说你如果要结果正确的话,那没关系啊,你water mark这这边你不是要拨慢那个表吗?你把它多拨慢一点对吧,你给它拨慢一个小时,那绝对该来的数都来了,对吧?啊,但是一般实际情况不会这么去干,对吧?他那个延迟就太高了啊,那你如果想让它这个,呃,就是实时性更好,延迟更小一点的话啊,那你可以把这个waterm延迟的就调小啊,你就调成50毫秒对吧,调成十毫秒,甚至你设成零,大家想设成零就相当于什么,设成零就相当于是我来了什么样的数据,就相当于我们这种机制,对吧,你来了什么样的数据,我就直接按照这个数据的。
18:10
这个时间戳就认为现在时间进展到哪里了,这就相当于是最快速的一个输出,对吧,实时性最强,就相当于是这种方式了,当然它跟那个直接用processing time还是略有区别,因为processing的话就没有考虑我们本身数据网络传输的延迟,对吧?这里边我们还是考虑到了数据网络传输的延迟的,是这个数据到了之后我就马上去出发,不考虑乱续是这种情形。啊啊,那那所以这里边就是我们会发现watermark可以让我们自己来平衡这两样了,你如果要让它足够快的话,那可能它的正确性就会受到影响,对吧,正确性就会缺失,那你如果要更快的话,你用processing time,那那正确性就更更保证不了了,对吧?网络延迟那个的数据也会丢掉啊,那另外还有就是说,你如果要想保证它正确的话,那你就没那么快,对吧,你就得设置的这个稍微的大一点,这就是watermark的含义。
我来说两句