zoukankan      html  css  js  c++  java
  • Flink MapState过期时间设置

    一、业务背景

    实时统计每天考勤人数

    使用MapState<Srting, Set>

    key:日期字符串 -> yyyyMMdd

    value:当天考勤员工ID,利用Set自动去重的特性统计当前考勤人数

    状态里只需要存储当天的数据,之前的数据可以清理掉。设置状态过期时间24小时,距离数据上一次修改超过24小时,该数据会被清理。

    // 设置状态过期配置
    StateTtlConfig ttlConfig = StateTtlConfig
            .newBuilder(Time.hours(24))
            .setUpdateType(StateTtlConfig.UpdateType.OnCreateAndWrite)
            .setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired)
            .build();
    MapStateDescriptor<String, Set> mapStateDescriptor = new MapStateDescriptor<>("MapStateDescriptor", String.class, Set.class);
    // 状态过期配置与壮状态绑定
    mapStateDescriptor.enableTimeToLive(ttlConfig);
    attendanceUserIdState = getRuntimeContext().getMapState(mapStateDescriptor);
    

    二、状态过期机制测试

    每隔1秒发送一条数据,状态有效期设置为3秒。打印状态里的数据

    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
    
        DataStreamSource<String> stringDataStreamSource = env.addSource(new SourceFunction<String>() {
            @Override
            public void run(SourceContext<String> sourceContext) throws Exception {
                while (true) {
                    TimeUnit.SECONDS.sleep(1);
                    sourceContext.collect(LocalDateTime.now().toString());
                }
            }
    
            @Override
            public void cancel() {
    
            }
        });
    
        SingleOutputStreamOperator<Tuple2<String, Integer>> keyStream = stringDataStreamSource.map(new MapFunction<String, Tuple2<String, Integer>>() {
            @Override
            public Tuple2 map(String s) {
                return Tuple2.of(s, 1);
            }
        });
    
        KeyedStream<Tuple2<String, Integer>, Tuple> tuple2TupleKeyedStream = keyStream.keyBy(1);
    
        SingleOutputStreamOperator<String> map = tuple2TupleKeyedStream.map(new RichMapFunction<Tuple2<String, Integer>, String>() {
            transient MapState<String, Object> state;
    
            @Override
            public void open(Configuration parameters) throws Exception {
                StateTtlConfig ttlConfig = StateTtlConfig.newBuilder(Time.seconds(3))
                        .setUpdateType(StateTtlConfig.UpdateType.OnReadAndWrite)
                        .setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired)
                        .build();
    
                MapStateDescriptor<String, Object> mapStateDescriptor = new MapStateDescriptor<>("mapStateDescriptor", String.class, Object.class);
                mapStateDescriptor.enableTimeToLive(ttlConfig);
                state = getRuntimeContext().getMapState(mapStateDescriptor);
            }
    
            @Override
            public String map(Tuple2<String, Integer> stringIntegerTuple2) throws Exception {
                state.put(stringIntegerTuple2.f0, new Object());
                Iterator<Map.Entry<String, Object>> iterator = state.iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, Object> next = iterator.next();
                    String key = next.getKey();
                    System.out.println(key);
                }
                return "====================" + LocalDateTime.now();
            }
        });
        map.print();
    
        env.execute("StateDemo");
    }
    

    运行结果

    2021-08-16T19:52:29.126
    9> ====================2021-08-16T19:52:29.183
    2021-08-16T19:52:29.126
    2021-08-16T19:52:30.136
    9> ====================2021-08-16T19:52:30.211
    2021-08-16T19:52:29.126
    2021-08-16T19:52:30.136
    2021-08-16T19:52:31.141
    9> ====================2021-08-16T19:52:31.242
    2021-08-16T19:52:30.136
    2021-08-16T19:52:31.141
    2021-08-16T19:52:32.144
    9> ====================2021-08-16T19:52:32.330
    2021-08-16T19:52:31.141
    2021-08-16T19:52:33.148
    2021-08-16T19:52:32.144
    9> ====================2021-08-16T19:52:33.355
    

    三、知识点

    报错:

    Queryable state is currently not supported with TTL

    检查UpdateType是否设置了Disabled。

    状态中的过期数据如何被清理

    默认情况下,只有在明确读出过期值时才会删除过期值,例如通过调用ValueState.value().

    注意:这意味着默认情况下,如果未读取过期状态的数据,则不会删除它,可能会导致状态不断增长。

    此外,还可以添加数据清理的策略,默认的和添加的策略都会生效。

    1.cleanupFullSnapshot

    在创建checkPoint或savepoint的完整快照时,不会包含状态中过期的数据。

    该配置还是不会影响本地状态存储的大小,但是整个作业的完整快照会减少。只有当用户从快照重新加载到本地时,才会清除用户本地的状态。

    StateTtlConfig ttlConfig = StateTtlConfig.newBuilder(Time.seconds(3))
            .setUpdateType(StateTtlConfig.UpdateType.OnCreateAndWrite)
            .setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired)
            .cleanupFullSnapshot()
            .build();
    

    2.cleanupIncrementally

    只适用于对内存状态后端(FsStateBackend和MemoryStateBackend)。

    在所有的状态上维护一个去全局的惰性迭代器。某些事件(例如状态访问)会触发清理。每次触发清理时,迭代器会向前遍历删除已过期数据。

    StateTtlConfig ttlConfig = StateTtlConfig.newBuilder(Time.seconds(3))
            .setUpdateType(StateTtlConfig.UpdateType.OnCreateAndWrite)
            .setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired)
            .cleanupIncrementally(10, false)
            .build();
    

    参数1:每次触发清理时要检查的数据数量。

    参数2:标志位,用于表示是否每条记录处理之后还出发清除逻辑。

    3.cleanupInRocksdbCompactFilter

    仅适用于RocksDB状态后端

    RocksDB会定期运行一步的压缩流程来合并数据,该过滤器适用生存时间检查状态条目的过期时间戳,并丢弃所有的过期值。

    StateTtlConfig ttlConfig = StateTtlConfig.newBuilder(Time.seconds(3))
            .setUpdateType(StateTtlConfig.UpdateType.OnCreateAndWrite)
            .setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired)
            .cleanupInRocksdbCompactFilter(100L)
            .build();
    
  • 相关阅读:
    table问题
    生成跟相应qq聊天
    查数组 indexOf()用法
    Ajax请求数据的两种方式
    Ajax面试题
    内部类及静态内部类的实例化
    为什么在开发中大部分的时候都在用session而Application基本上都不去使用?
    Java序列化与反序列化
    Java反射机制
    Java中线程同步的方法
  • 原文地址:https://www.cnblogs.com/yangyh11/p/15150388.html
Copyright © 2011-2022 走看看