12、Flink 的 Keyed State 代码示例

1、KeyedState 用例

import org.apache.flink.api.common.functions.AggregateFunction;
import org.apache.flink.api.common.functions.ReduceFunction;
import org.apache.flink.api.common.state.*;
import org.apache.flink.api.common.typeinfo.TypeHint;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.KeyedProcessFunction;
import org.apache.flink.util.Collector;

public class _01_KeyedState {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        DataStreamSource<String> source = env.socketTextStream("localhost", 8888);

        source.keyBy(e -> e)
                .process(new KeyedProcessFunction<String, String, Tuple2<String, Integer>>() {
                    private ValueState<Tuple2<String, Integer>> valueState;
                    private ListState<String> listState;
                    private ReducingState<Integer> reducingState;
                    private AggregatingState<Integer, String> aggregatingState;
                    private MapState<String, Integer> mapState;

                    @Override
                    public void open(Configuration parameters) throws Exception {
                        ValueStateDescriptor<Tuple2<String, Integer>> valueStateDescriptor = new ValueStateDescriptor<Tuple2<String, Integer>>("valueState", TypeInformation.of(new TypeHint<Tuple2<String, Integer>>() {
                        }));
                        ListStateDescriptor<String> listStateDescriptor = new ListStateDescriptor<>("listState", String.class);
                        ReducingStateDescriptor<Integer> reducingStateDescriptor = new ReducingStateDescriptor<Integer>("reduceingState", new ReduceFunction<Integer>() {
                            @Override
                            public Integer reduce(Integer value1, Integer value2) throws Exception {
                                return value1 + value2;
                            }
                        }, Integer.class);
                        AggregatingStateDescriptor<Integer, Integer, String> aggregatingStateDescriptor = new AggregatingStateDescriptor<>("aggregatingState", new AggregateFunction<Integer, Integer, String>() {
                            @Override
                            public Integer createAccumulator() {
                                return 0;
                            }

                            @Override
                            public Integer add(Integer value, Integer accumulator) {
                                return value + accumulator;
                            }

                            @Override
                            public String getResult(Integer accumulator) {
                                return "res=>" + accumulator;
                            }

                            @Override
                            public Integer merge(Integer a, Integer b) {
                                return a + b;
                            }
                        }, Integer.class);

                        MapStateDescriptor<String, Integer> mapStateDescriptor = new MapStateDescriptor<>("mapState", String.class, Integer.class);

                        valueState = getRuntimeContext().getState(valueStateDescriptor);
                        listState = getRuntimeContext().getListState(listStateDescriptor);
                        reducingState = getRuntimeContext().getReducingState(reducingStateDescriptor);
                        aggregatingState = getRuntimeContext().getAggregatingState(aggregatingStateDescriptor);
                        mapState = getRuntimeContext().getMapState(mapStateDescriptor);
                    }

                    @Override
                    public void processElement(String input, KeyedProcessFunction<String, String, Tuple2<String, Integer>>.Context ctx, Collector<Tuple2<String, Integer>> out) throws Exception {
                        Tuple2<String, Integer> res = valueState.value();
                        if (res == null) {
                            res = new Tuple2<>(input, 1);
                            valueState.update(res);
                        } else {
                            res.f1 += 1;
                            valueState.update(res);
                        }

                        listState.add(input);

                        reducingState.add(1);

                        aggregatingState.add(1);

                        if (mapState.contains(input)) {
                            Integer beforeNum = mapState.get(input);
                            mapState.put(input, beforeNum + 1);
                        } else {
                            mapState.put(input, 1);
                        }
                    }

                    @Override
                    public void close() throws Exception {
                        System.out.println("valueState=>"+valueState.value());
                        valueState.clear();
                        System.out.println("listState=>"+listState.get());
                        listState.clear();
                        System.out.println("reduceState=>"+reducingState.get());
                        reducingState.clear();
                        System.out.println("aggregatingState=>"+aggregatingState.get());
                        aggregatingState.clear();
                        System.out.println("mapState=>"+mapState.entries().toString());
                        mapState.clear();
                    }
                });

        env.execute();
    }
}

输入与输出

 依次输出:a,b,c,a,b,c
  预期输出结果:
  每个key的数据明细 listState:[a,a],[b,b],[c,c]
  每个key的数量带key valueState:[a,2],[b,2],[c,2]
  每个key的数量不带key reduceState:2,2,2
  每个key的数量不带key,且输入和输出数据类型不同 aggregatingState:res=>2,res=>2,res=>2
  每个key的数量带key mapState:[a,2],[b,2],[c,2]
 
  实际输出结果:
 
  valueState=>(a,2)
  valueState=>(b,2)
  valueState=>(c,2)
 
  listState=>[a, a]
  listState=>[b, b]
  listState=>[c, c]
 
  reduceState=>2
  reduceState=>2
  reduceState=>2
 
  aggregatingState=>res=>2
  aggregatingState=>res=>2
  aggregatingState=>res=>2
 
  mapState=>[a=2]
  mapState=>[b=2]
  mapState=>[c=2]

2、KeyedStateTTL

import org.apache.flink.api.common.state.StateTtlConfig;
import org.apache.flink.api.common.state.ValueState;
import org.apache.flink.api.common.state.ValueStateDescriptor;
import org.apache.flink.api.common.typeinfo.TypeHint;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.CheckpointingMode;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.KeyedProcessFunction;
import org.apache.flink.util.Collector;

import java.time.Duration;

public class _02_KeyedStateTTL {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        DataStreamSource<String> source = env.socketTextStream("localhost", 8888);
        env.enableCheckpointing(3000, CheckpointingMode.EXACTLY_ONCE);

        source.keyBy(e -> e)
                .process(new KeyedProcessFunction<String, String, Tuple2<String, Integer>>() {
                    private ValueState<Tuple2<String, Integer>> valueState;

                    @Override
                    public void open(Configuration parameters) throws Exception {
                        ValueStateDescriptor<Tuple2<String, Integer>> valueStateDescriptor = new ValueStateDescriptor<Tuple2<String, Integer>>("valueState", TypeInformation.of(new TypeHint<Tuple2<String, Integer>>() {
                        }));

                        // 只支持 KeyedState 的 TTL
                        // 只支持 processing time 的 TTL
                        StateTtlConfig stateTtlConfig = StateTtlConfig.newBuilder(Duration.ofSeconds(5))
                                // TTL 的更新策略
                                // StateTtlConfig.UpdateType.OnCreateAndWrite - 仅在创建和写入时更新
                                // StateTtlConfig.UpdateType.OnReadAndWrite - 读取时也更新
                                .setUpdateType(StateTtlConfig.UpdateType.OnCreateAndWrite)
                                // 状态的可见性
                                // StateTtlConfig.StateVisibility.NeverReturnExpired - 不返回过期数据
                                // StateTtlConfig.StateVisibility.ReturnExpiredIfNotCleanedUp - 会返回过期但未清理的数据
                                .setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired)
                                // 状态的清理策略,默认过期数据会在读取的时候被删除
                                // cleanupFullSnapshot() 全量快照时进行清理
                                // cleanupIncrementally(10, true) 增量数据清理
                                // cleanupInRocksdbCompactFilter(1000, Duration.ofHours(1)) RocksDB 压缩过滤器
                                .cleanupFullSnapshot()
                                .build();

                        valueStateDescriptor.enableTimeToLive(stateTtlConfig);

                        valueState = getRuntimeContext().getState(valueStateDescriptor);
                    }

                    @Override
                    public void processElement(String input, KeyedProcessFunction<String, String, Tuple2<String, Integer>>.Context ctx, Collector<Tuple2<String, Integer>> out) throws Exception {
                        Tuple2<String, Integer> res = valueState.value();
                        if (res == null) {
                            res = new Tuple2<>(input, 1);
                            valueState.update(res);
                            out.collect(res);
                        } else {
                            res.f1 += 1;
                            valueState.update(res);
                            out.collect(res);
                        }
                    }

                    @Override
                    public void close() throws Exception {
                        System.out.println("valueState=>" + valueState.value());
                        valueState.clear();
                    }
                })
                .print("res=>");

        env.execute();
    }
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个基于 Flink SQL API 的单元测试代码示例,该代码测试了一个简单的 Flink SQL 查询: ```java import org.apache.flink.api.common.typeinfo.Types; import org.apache.flink.api.java.ExecutionEnvironment; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.table.api.Table; import org.apache.flink.table.api.bridge.java.BatchTableEnvironment; import org.apache.flink.table.api.bridge.java.StreamTableEnvironment; import org.apache.flink.table.api.EnvironmentSettings; import org.apache.flink.types.Row; import org.junit.Test; import static org.junit.Assert.assertEquals; public class FlinkSqlUnitTest { @Test public void testFlinkSql() throws Exception { // 创建执行环境 StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); StreamTableEnvironment tEnv = StreamTableEnvironment.create(env); // 创建测试数据 env.setParallelism(1); env.fromElements(Tuple2.of("Alice", 23), Tuple2.of("Bob", 35), Tuple2.of("Charlie", 40)) .toTable(tEnv, "name, age"); // 执行测试任务 Table result = tEnv.sqlQuery("SELECT * FROM name_age WHERE age > 30"); // 验证测试结果 tEnv.toRetractStream(result, Row.class) .returns(Types.TUPLE(Types.BOOLEAN, Types.ROW_NAMED(new String[]{"name", "age"}, Types.STRING, Types.INT))) .map(tuple -> tuple.f1) .returns(Types.ROW_NAMED(new String[]{"name", "age"}, Types.STRING, Types.INT)) .addSink(new StreamSinkFunction<>()); // 执行测试任务 env.execute(); } } ``` 该代码使用 Flink 的 StreamTableEnvironment,创建了一个简单的表,然后执行了一个 Flink SQL 查询,查询年龄大于 30 的人的信息。最后,使用 Flink 的 TestingUtils 工具类来验证测试结果是否正确。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫猫爱吃小鱼粮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值