00:00
接下来给大家开启flink里边另外一部分很重要的内容,那就是所谓的状态管理啊,这一部分里边呢,主要有这么几个内容啊,首先我们先说一下,一直在说状态,那flink里边的状态到底是什么呢?呃,讲一下它的概念啊,另外就是flink里边的状态分成两大类,一类叫做operator state啊,这个翻译过来有时候就叫做算子状态。另外一大类呢,叫做kid,有时候翻译叫做监控状态,这个呃,看怎么去定义啊,因为它英文是叫做kid state,大家还记得那个kid stream对吧?啊,就是相当于是定义了一个K之后分组分分区了之后呢,呃,类似于这样的一个流对吧?那这里边的这个kid sit呢,大家也可以认为是一个分组状态啊,就是针对每一个K有对应的这个状态啊,我们这里边翻译是叫做监控状态,最后还有一个概念是所谓的状态后端啊,这就是我们这节课里边的主要内容,首先。
01:00
先来看一下弗林克里边状态到底是什么,那大家想一下这个弗林里边状态到底是什么呀?啊,在这个flink里边,其实处理处理这个数据的时候啊,其实有不同的形式的,大家仔细想一下的话,你像我们讲的那个简单基本转换算子map filter flat map,大家想它里边有状态吗?他当时我们讲的时候,它其实就是来一个直接处理一个直接输出了,对吧?啊,来一个直接输出了,它并不依赖其他的数据,也不依赖比方说之前我们聚合起来的某种结果,某个状态,对吧?那它不依赖任何别的东西,所以像这些算子,一般我们认为它就是一个无状态的这样的一个算子,或者说一个任务,对吧?啊,那但是有一些呢,或者说弗link里边更多的任务,更多的算子。它是会有状态的,比如说像我们前面介绍的window对吧状态,呃,这个窗口,或者说我们前面讲过的像reduce操作对吧?呃,像像做这个聚合的这些操作,大家想一下之前我们做那个,呃,比方说啊做sum或者做做这个明max by的时候,做sum的时候,它是不是每来一条数据,不是仅根据当前的数据就能输出一个结果啊,我对还要知道之前所有数据聚合起来那个求和那个sum值,所以大家会想到当前是不是我必须要保持着这样的一个数据放在自己的内存里面啊,就是之前所有数据求和的那个数啊,所以大家会发现对于像这样的场景啊,由一个任务来维护的。
02:37
然后呢,是用来计算某个结果的,额外的需要的那些数据就不仅仅是基于当前输入的数据,还需要额外的一些数据,那么这些数据就叫做当前任务的状态,好,那所以大家从这个架构上来看的话,我们整个处理的流程就是来了一个输入的数据,输入给这个task这个任务,那这个任务接下来呢,那他自己应该有一个状态,对吧?他从自己的内存里面把状态拿出来,结合当前的这个数据,诶,做某种计算,大家想如果求和的话,直接加对吧,如果是max y的话,那求一个最大值,另外的话求一个最小值,然后得到的结果,诶,大家注意啊,是不是还应该有可能要更新状态啊。
03:23
因为你如果求和的话,是不是应该把我现在叠加之后的那个和再更新回去啊,所以大家看这里边有一个状态的读取和写入,然后得到结果是不是就可以发出去了啊,所以大家看这个完整的流程,这就是我们所说的那个,呃,常规的事件,事件处理的那种方式啊,数据处理的方式,我们的那个服务器是不是也是这种模式啊,用户那边发一个请求过来,我去查询当前的业务数据库,对吧?然后更新业务数据库,返回用户那边一个一个最终的一个响应结果啊,所以这个其实是整体流程非常的相近啊。那当前我们的这个状态呢?
04:00
大家注意它不是放在数据库里,它一般就是放在本地内存,对,因为你要快嘛,所以我们这里的状态可以认为就是一个本地变量啊,那么既然是一个本地变量,那就应该能被我们当前任务的所有业务逻辑应该都能够访问得到,对吧?啊,只要它这个变量的可见范围内啊,那当前就都可以去直接把它拿到。呃,那么对于这个flink而言,它其实是会帮我们进行这个状态管理的,因为大家会想到在这里边就是你如果只是把它当成一个本地变量的话,这个还比较简单,那我直接随便定义一个变量不也都一样嘛,对吧?代码里边随便随便定义随便用啊,那所有定义出来本地变量都可以当做状态用吗?大家想一想,能不能这么做?不能,哎,那主要的原因在哪里呢?主对,主要就是大家考虑考虑到我们现在有容错的考量,对吧?啊,就是你如果要做容错的时候,是不是我当前是一个分布式的集群啊,是不是每一个分布式节点,每一个分区任务都要把自己的状态做一个保存啊。
05:11
哎,那你在这个保存的时候,首先是涉及到一个就是序列化反序列化的一个一个问题,对吧?诶,那那这个,呃,序列化反序列化的这个过程当中,你得知道它具体的这个类型到底是什么,然后怎么样去做存储,怎么样去做读取解析,那另外呢,你如果要是出现故障,然后重新启动的时候,又会涉及到一个另外的问题,就是大家想我是不是有可能并行度会调整啊。因为你一旦发生故障,哎,那可能我这个并行度调整有两种场景,就是一种场景是我有一台机器真的挂了。那挂了之后大家想,之前我的集群是十台机器,现在挂了一台机器,是不是现在我的并行度就得被迫降低啊?哎,这是一种场景,并行度要降低,那还有一种场景是之前挂了有可能是因为什么?是不是因为内存不够用了呀,对吧?我存的这个状态越来越多啊,然后定义的这个对象变量也越来越多,然后out of memory对吧?OM了直接挂了,那接下来我现在要去重新启动,你不能直接就原样启动,那到最后还要挂,那是不是我应该扩容啊,扩容的话并行度是不是就可以调整啊?因为大家知道,只要我代码里边没有写死并行度,是不是我可以提交drop补的时候再指定它的执行平行度啊。哎,所以这种情况下就又会涉及到另外一个问题,我读取之前的状态出来之后,是不是接下来我这个状态有可能要。
06:39
有可能,如果并行度变小的话,是不是之前十份状态现在要变成九个,我要合并啊,如果并行度变大,为了让大家也可能想到你如果并行度变大扩容的话,我可以扩起来的那几个状态就没有,我直接就全放到那个原先的几个里面不就完了吗?那大家想你直接放到原先那几个的话,状态是不是又没分开啊,那到一一上去之后,是不是状态又撑满了?
07:04
所以是不是还要做一个分流啊,分配状态对吧,有时候要和有时要分配状态,所以。那大家就想到了,这个过程是不是很麻烦呀,如果说这个机制全让我们自己去手动实现的话,哎哟,太复杂了,所以好在flink给我们把这一切啊全部在底层给我们做了实现,它有一整套完善的状态管理机制,这个状态管理机制就包括了状态一致性的保证,对吧,就是你容错之后,最后我恢复出来之后,状态还是一样的,因为大家想这个分布式架构嘛,你当时保存的那个状态,我恢复之后能不能就刚好对上之前处理的那个状态呢?对吧?因为他们互相之间都是独立进行的嘛,啊并不知道别人的状态到了哪,然后另外还有就是啊,发生故障的时候怎么样去处理呢?怎么样恢复呢?另外还有就是怎么样做高效的存储访问呢?对吧,序列化反序列化啊,所以flink底层帮我们把这些东西都搞定。
08:03
那我们的开发压力就小多了,我们就可以专注于业务逻辑的书写,就不用去管它的这个底层啊状态到底怎么去分配了,对吧?啊,所以其实在flink里边状态主要是分成了两大类,如果从这个意义上来讲啊,分成了两大类,一大类叫做managed state。Managed state啊,另外一类叫做raw state啊,所以顾名思义managed state就是啊,就是被flink这个状态管理机制直接帮我们管理起来的这一整套的所有的状态。而rotate就是,呃,就是不被flink管理对吧?呃,我要求就是你直接给我一一个内存空间,然后我自己去定义它到底该怎么做怎么做对吧?啊,这个就比较复杂一点,当然如果说大家想要自己去控制底层的一些逻辑的话,也可以用这个RO state,一般我们开发的时候不要用这个对吧,直接用这个flink管理机制帮我们搞定的manage state就可以了。
我来说两句