Flink学习(5)——state(状态)管理

1. 什么是flink state

由一个任务维护,并且用来计算某个结果的数据,都属于这个任务的状态,可以认为状态就是一个本地变量,可以被任务的业务逻辑访问。

Flink 会进行状态管理,包括状态一致性、故障处理以及高效存储和访问,以 便开发人员可以专注于应用程序的逻辑。

Flink有两种基本类型的状态:托管状态(Managed State)和原生状态(Raw State)。

两者的区别:Managed State是由Flink管理的,Flink帮忙存储、恢复和优化,Raw State是开发者自己管理的,需要自己序列化。

具体区别有:

1. 从状态管理的方式上来说,Managed State由Flink Runtime托管,状态是自动存储、自动恢复的,Flink在存储管理和持久化上做了一些优化。当横向伸缩,或者说修改Flink应用的并行度时,状态也能自动重新分布到多个并行实例上。Raw State是用户自定义的状态。
从状态的数据结构上来说,Managed State支持了一系列常见的数据结构,如ValueState、ListState、MapState等。Raw State只支持字节,任何上层数据结构需要序列化为字节数组。使用时,需要用户自己序列化,以非常底层的字节数组形式存储,Flink并不知道存储的是什么样的数据结构。
2. 从具体使用场景来说,绝大多数的算子都可以通过继承Rich函数类或其他提供好的接口类,在里面使用Managed State。Raw State是在已有算子和Managed State不够用时,用户自定义算子时使用。


对Managed State继续细分,它又有两种类型:Keyed State和Operator State。

为了自定义Flink的算子,可以重写Rich Function接口类,比如RichFlatMapFunction。使用Keyed State时,通过重写Rich Function接口类,在里面创建和访问状态。对于Operator State,还需进一步实现CheckpointedFunction接口。

2. 算子状态(operator state)

算子状态的作用范围限定为当前算子任务,当前算子任务中的所有数据都可以访问到相同的状态,但不能被另一个算子任务访问,哪怕是处理同一类算子的并行任务。

2.1 算子状态的数据结构

1. 列表状态

即采用List的数据结构,存储多个数据作为状态数据

2. 联合列表状态

也是采用List的数据结构,但和列表状态的区别在于其在发生故障时,或者从保存点(savepoint)启动应用程序时如何恢复。

列表状态在恢复程序的时候,会依据恢复后的并行度,将列表中的状态数据进行拆分,拆分为新的列表状态后在分发给各个并行算子。

而联合列表状态则是将所有的列表状态合并为一个完整的列表状态,然后给每一个新的并行算子任务发送一份作为自身状态。

3. 广播状态:这种情况比较特殊,其适用于各个算子之间要求状态值相同的情况,比如说一些配置参数,各个算子公用一套配置参数,这种情况就比较适合广播状态。

2.2 算子状态api使用

算子状态的api应用较少,比较常见的 operator state 是 source state,例如记录当前 source 的 offset,这个在以kafka作为source的时候非常常用,我们可以通过记录offset来判断kafka中的消息积压情况。

主要是在算子实现类中实现ListCheckpointed接口,就可以实现算子状态的存储和恢复。

还有一种实现CheckpointedFunction接口的,但比较复杂,实现ListCheckpointed比较简单清晰,但通过CheckpointedFunction接口实现会比较灵活。

官方参考链接:https://ci.apache.org/projects/flink/flink-docs-release-1.10/dev/stream/state/state.html#listcheckpointed

public class OperatorStateTest1 {

    public static void main(String[] args) throws Exception {

        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        //从文本文件中按行读取数据
        DataStreamSource<String> streamSource = env.readTextFile("word.txt");
        
        SingleOutputStreamOperator<Tuple2<String, Integer>> sum = streamSource.flatMap(new WordCount.MyFlatMapper())
                .keyBy(0)
                .sum(1);

        sum.print();
        env.execute();
    }

    //通过算子状态来记录统计一下处理的数据数量
    public static class MyFlatMapper implements FlatMapFunction<String, Tuple2<String, Integer>>, ListCheckpointed<Integer> {

        //其实算子状态很简单,直接定义一个变量就能实现所需要的数据量统计
        int count = 0;
        //仅通过count这个状态变量我们依据实现了所需要的的统计功能,但是问题在于,当程序异常终止又重新启动后,
        //flink要如何恢复这个变量值?
        //我们肯定不能重新读取数据,把所有数据重新处理一遍
        //所以我们可以通过Flink提供的接口来实现状态数据的快照保存和恢复
        //MyFlatMapper实现ListCheckpointed接口即可


        public void flatMap(String s, Collector<Tuple2<String, Integer>> collector) throws Exception {
            //统计一下处理一条数据
            count++;
            //按空格分词
            String[] s1 = s.split(" "
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值