细说Flink状态管理
一:“背景”
Flink 的状态管理是啥,要讲明白这个事情,我们就要知道为什么有Flink的状态管理呢?兄弟们想想,如果Flink的流式任务中要计算某个特定时间范围内的统计数据,就比如5min内的某类商品的订单量,我们是不是要把5min内的所有的数据拿到,然后做一个总和统计。
那么问题来了,Flink 的流式任务中,第1s中进入Flink的数据如果没有其他特殊情况下,是会把这个数据继续输出给下游的,如果我们要留住,那必然是需要用个缓存池缓存起来嘛,这些缓存起来的数据一般会进入到我们的所谓的状态里面,就是我们所说的State。
那么兄弟们可能会问到,对于这种不关心前面的数据的情况下,是不是需要缓存啊,你是不是傻,当然不需要啊,关心干嘛,不是给自己增加负担吗?比如我们常用的map,filter, flatMap 不就是这种情况嘛,这个是无状态管理。
二:分类
其实Flink 的状态分为两大类,分别是KeyedState 和 OperatorState;根据大致的意思我们就明白,KeyedState就是我们FLink 中用到的KeyBy 算子会触发这个状态大类,而OperatorState 就是我们常见的算子状态大类(包括诸如ReducingState, AggragatingState 等)。但是兄弟们,状态这个东西最本质的还是某些需要缓存记录的数据,我之前还一直以为这个状态是像我们现实世界中所理解的一样是某个数据是否可用等的情况,不是,就是比如订单前一分钟的订单金额这种的。
2.1:KeyedState
KeyedState 顾名思义就是某个key对应的某些状态的值,因为我们在进行keyBy的时候,我们是需要知道这个对应的key的value值有哪些,也需要知道这个value值有多少等,所以这个KeyedState 一般分为ValueState,ListState, MapState等,分别存储这些key对应的不同的状态类型,也就是不同的数据情况。假如我们按照订单id去进行分组的话,某个valueState 就是这个订单id所对应的金额存储,而这个ListState 就是对应的这个订单id的子订单的id的存储;MapState 或许就是这个订单Id 和子订单的一一对应关系的存储。大家只要理解成数据存储就可以了。
2.2:OperatorState
大家想象下这个场景,我们在进行相应的流计算的时候,假设没有进行对应的KeyBy这样的算子,只有一些简单的过滤逻辑,就会对应到一些map或者filter这样的算子,那么算子过滤之后的数据存储在哪里呢?这个时候这些算子就是放在对应的OperatorState,它一般分为ListState,valueState等,顾名思义就是存储对应的列表和值的。
三:状态存储
上述的状态很重要,所以Flink 肯定就要把相应的状态给保存下来,那么保存在哪里呢?FLink 提供了三个存储的介质,分别是MemoryStateBackend, RocksDBStateBackend 和 FilesystemStateBackend
状态的数据和checkpoint 的数据都存储在哪里呢?
3.1: 如果是memoryStateBackend, 状态的数据是存储在tm的内存中,checkpoint 的数据是存储在jm 的内存中
3.2: 如果是RocksDBStateBackend,状态的数据是存储在RockDB(内存和磁盘);对应的checkpoint 的数据是一般存储在hdfs 上的
3.3: 如果是FilesystemStateBackend, 那么状态的数据是存储在tm的内存中;那么对应的checkpoint 的数据是一般存储在hdfs 上的
兄弟们可能会想,checkpoint 到底是个什么样的东西?我就简单地说下,checkpoint 的中文意思是检查点,其实也就是一个数据备份的机制,把所有的状态数据做一个备份,以便后期任务出现异常的时候可以把这些对应的状态恢复过来。
那么这就涉及到一个问题,在开发环境和生产环境的时候我们对应的状态应该存储在哪里呢?对于开发和测试环境来说,因为我们一般都是用自己的一个测试数据,所以状态数据不是很大,所以我们可以选择第一个方式,直接设置SET ‘state.backend’ = ‘memory’; – 设置状态后端为内存(MemoryStateBackend),默认不设置checkpoint,这样checkpoint 对应的数据就会存储在jm的内存中;
如果是生产环境,理论上来说状态后端的存储可以设置为RocksDB 和FileSystem, 但是如果数据量相对来说比较大的情况下,还是建议设置成RocksDB, 因为RockDB 支持增量的状态存储,相对来说存储的状态可以更多,Flink sql 设置案例如下:
state.backend RocksDB
execution.checkpointing.externalized-checkpoint-retention RETAIN_ON_CANCELLATION
execution.checkpointing.interval 30s
execution.checkpointing.mode EXACTLY_ONCE
state.checkpoints.dir hdfs://user/kafka/kafka-hive/checkpoints