Flink状态管理

本文介绍了ApacheFlink中五种关键的状态管理方式:值状态、列表状态、映射状态、归约状态和聚合状态,以及状态生存时间和状态后端的选择,以实现在流处理中的状态持久化和计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

值状态(ValueState)

列表状态(ListState)

Map状态(MapState)

归约状态(ReducingState)

聚合状态(AggregatingState)

广播状态(BroadcastState)

状态生存时间(TTL)

状态后端


值状态(ValueState)

        Flink状态保留一个值,例如Integer、Long类型。

        常用的方法如下

value()  // 获取当前状态的值
update() // 更新当前状态的值

        下面实现一个简单案例,来加深理解。watersensor对象的 ts 表示水位值,现在需要找到连续两条水位值相差大于10的数据,这时候就可以用值状态来存储上一条水位值。

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

        SingleOutputStreamOperator<WaterSensor> sensorDS = env
                .socketTextStream("node1", 7777)
                .map(new WaterSensorMapFunction())
                .assignTimestampsAndWatermarks(
                        WatermarkStrategy
                                .<WaterSensor>forBoundedOutOfOrderness(Duration.ofSeconds(3))
                                .withTimestampAssigner((value,ts) -> value.getTs()*1000L)
                );

        sensorDS
                .keyBy(value -> value.getId())
                .process(new KeyedProcessFunction<String, WaterSensor, String>() {

                    // TODO 1.定义状态
                    ValueState<Integer>  lastValueState;

                    @Override
                    public void open(Configuration parameters) throws Exception {
                        super.open(parameters);
                        // TODO 2.在open方法中,初始化状态
                        // 状态描述器两个参数:第一个参数,起个名字,不重复;第二个参数,存储的类型
                        lastValueState = getRuntimeContext().getState(new ValueStateDescriptor<Integer>("valueState", Types.INT));
                    }

                    @Override
                    public void processElement(WaterSensor waterSensor, Context context, Collector<String> collector) throws Exception {

                        // 取出上一条水位数据(存储在值状态中)
                        int lastVc = lastValueState.value() == null ? 0 : lastValueState.value();
                        Integer vc = waterSensor.vc;
                        if(Math.abs(lastVc-vc) > 10){
                            collector.collect("传感器:" + context.getCurrentKey() + "当前水位值" + vc + ",上一条水位值" + lastVc + "相差超过10");
                        }

                        lastValueState.update(vc);

                    }
                })
                .print();

        env.execute();
    }

        由于使用按键分区状态,可以看到,s2,11,11这条数据,他的上一条tc应该为null,值状态也为空,代码中手动赋值为0,因此这条数据也被打印输出。因此,也证明了每一个key都有一个状态。

列表状态(ListState)

        将需要保存的值,以列表的形式存储起来。

        常用方法如下

ListState.get();            //取出 list状态 本组的数据,是一个Iterable
ListState.add();            // 向 list状态 本组 添加一个元素
ListState.addAll();         // 向 list状态 本组 添加多个元素
ListState.update();         // 更新 list状态 本组数据(覆盖)
ListState.clear();          // 清空List状态 本组数据

        下面实现一个案例,输出每个传感器(id)最高的三个水位值。

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

        SingleOutputStreamOperator<WaterSensor> sensorDS = env
                .socketTextStream("node1", 7777)
                .map(new WaterSensorMapFunction())
                .assignTimestampsAndWatermarks(
                        WatermarkStrategy
                                .<WaterSensor>forBoundedOutOfOrderness(Duration.ofSeconds(3))
                                .withTimestampAssigner((value,ts) -> value.getTs()*1000L)
                );

        // 输出每个传感器最高的3个水位值
        sensorDS.keyBy(value -> value.getId())
                .process(new KeyedProcessFunction<String, WaterSensor, String>() {

                    ListState<Integer> listState;

                    @Override
                    public void open(Configuration parameters) throws Exception {
                        super.open(parameters);
                        listState = getRuntimeContext().getListState(new ListStateDescriptor("vclistState", Types.INT));
                    }

                    @Override
                    public void processElement(WaterSensor waterSensor, Context context, Collector<String> collector) throws Exception {

                        // 1、来一条数据存储一条
                        listState.add(waterSensor.vc);

                        // 2、从list状态拿出来(Iterable), 拷贝到一个List中,排序, 只留3个最大的
                        Iterable<Integer> iter = listState.get();
                        List<Integer> list = new ArrayList<>();
                        for (Integer vc : iter) {
                            list.add(vc);
                        }
                        // 降序,后 - 前
                        list.sort((o1,o2) -> (o2-o1));

                        // 3、只保留最大的3个(list中的个数一定是连续变大,一超过3就立即清理即可)
                        if(list.size() > 3){
                            list.remove(3);
       
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值