Flink教程(13) Keyed State状态管理之ValueState的使用 温差报警

本文是Flink教程系列的一部分,详细介绍了KeyedState中的ValueState使用。通过一个温差报警的实验案例,展示了如何定义ValueStateDescriptor,如何获取和更新ValueState,以及在KeyedProcessFunction中处理数据流的过程,帮助读者理解Flink的状态管理机制。
摘要由CSDN通过智能技术生成

系列文章

Flink教程(13) Keyed State状态管理之ValueState的使用 温差报警
Flink教程(14) Keyed State状态管理之MapState使用案例
Flink教程(15) Keyed State状态管理之ListState使用 ValueState实现
Flink教程(16) Keyed State状态管理之ReducingState使用案例 求最大值
Flink教程(17) Keyed State状态管理之AggregatingState使用案例 求平均值

一、ValueState的方法

ValueState的使用比较简单,方法如下图

  • 用ValueStateDescriptor定义ValueState的描述器
  • value()方法获取值
  • update(T value)方法更新值
    在这里插入图片描述

二、实验案例

1. 温度Bean

public class SensorRecord {

    private String id;

    private Double lastRecord;

    private Double record;

    private LocalDateTime time;
    
    //省略其他get set

	//将Long类型的时间值
    public Long getTimeEpochMilli() {
        return time.toInstant(ZoneOffset.of("+8")).toEpochMilli();
    }
}

2. 将字符串映射成SensorRecord对象

/**
 * 将字符串映射成SensorRecord对象
 */
public static class BeanMap implements MapFunction<String, SensorRecord> {

    @Override
    public SensorRecord map(String s) throws Exception {
        if (StringUtils.isNotBlank(s)) {
            String[] split = s.split(",");
            if (split != null && split.length == 3) {
                return new SensorRecord(
                        split[0],
                        Double.valueOf(split[1]),
                        LocalDateTime.parse(split[2], FormatterConstant.commonDtf));
            }
        }
        return null;
    }
}

3. ValueStateDescriptor描述器

描述器:指定id=last-temp,和类型是Double类型

//描述器:指定id=last-temp,和类型是Double
ValueStateDescriptor<Double> lastTempDescriptor = new ValueStateDescriptor<Double>(
        "last-temp",
        Double.class);

lastTemp = getRuntimeContext().getState(lastTempDescriptor);

4. 程序主体

指定温差超过10就返回

public class Test01_ValueState {

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

        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        //方便测试,设置为1
        env.setParallelism(1);

        DataStreamSource<String> source = env.socketTextStream(BaseConstant.URL, BaseConstant.PORT);

        /*
        设置watermark和指定时间属性
         */
        SingleOutputStreamOperator<SensorRecord> dataStream = source
                .map(new SensorRecordUtils.BeanMap())
                .assignTimestampsAndWatermarks(
                        WatermarkStrategy.<SensorRecord>forBoundedOutOfOrderness(Duration.ofSeconds(1))
                                .withTimestampAssigner(new SerializableTimestampAssigner<SensorRecord>() {

                                    @Override
                                    public long extractTimestamp(SensorRecord element, long recordTimestamp) {
                                        return element.getTimeEpochMilli();
                                    }
                                })
                );

        dataStream
                .keyBy(SensorRecord::getId)
                .process(new MyKeyedProcessFunction(10))
                .print();

        env.execute();
    }
}

5. KeyedProcessFunction处理数据流

public static class MyKeyedProcessFunction extends KeyedProcessFunction<String, SensorRecord, SensorRecord> {

    private int tempDiff;

    public MyKeyedProcessFunction(int tempDiff) {
        this.tempDiff = tempDiff;
    }

    private transient ValueState<Double> lastTemp;

    @Override
    public void open(Configuration parameters) throws Exception {
        super.open(parameters);

        ValueStateDescriptor<Double> lastTempDescriptor = new ValueStateDescriptor<Double>(
                "last-temp",
                Double.class);

        lastTemp = getRuntimeContext().getState(lastTempDescriptor);
    }

    @Override
    public void processElement(SensorRecord value, Context ctx, Collector<SensorRecord> out) throws Exception {

        //第一条数据,需要处理
        if (lastTemp.value() == null){
            lastTemp.update(Double.MIN_VALUE);
        }
        //从第二条数据开始比较两者的差值
        else if (Math.abs(value.getRecord() - lastTemp.value()) > tempDiff){
            value.setLastRecord(lastTemp.value());
            out.collect(value);
        }

        //value state 记录最新的值
        if (value.getRecord() != null){
            lastTemp.update(value.getRecord());
        }
    }
}
Flink中,ValueState是一种状态类型,可以用于存储单个值。它通常用于对输入流中的某些值进行聚合或累积计算,例如计算平均值或求和。以下是使用ValueState的示例代码: ``` // 导入必要的库 import org.apache.flink.api.common.functions.RichFlatMapFunction; import org.apache.flink.api.common.state.ValueState; import org.apache.flink.api.common.state.ValueStateDescriptor; import org.apache.flink.configuration.Configuration; import org.apache.flink.util.Collector; // 实现一个 RichFlatMapFunction public class MyFlatMapFunction extends RichFlatMapFunction<Integer, Integer> { private transient ValueState<Integer> sumState; @Override public void open(Configuration config) { // 初始化 ValueState ValueStateDescriptor<Integer> sumStateDescriptor = new ValueStateDescriptor<>("sum", Integer.class); sumState = getRuntimeContext().getState(sumStateDescriptor); } @Override public void flatMap(Integer value, Collector<Integer> out) throws Exception { // 从 ValueState 中获取之前的累加结果 Integer sum = sumState.value(); if (sum == null) { sum = 0; } // 进行累加计算 sum += value; // 更新 ValueState 中的值 sumState.update(sum); // 输出结果 out.collect(sum); } } ``` 在上面的示例中,我们实现了一个 RichFlatMapFunction,使用ValueState对输入流中的整数进行累加计算,并将结果输出。在open()方法中,我们初始化了一个名为“sum”的ValueState。在flatMap()方法中,我们首先从ValueState中获取之前的累加结果,如果ValueState中没有值,则将sum初始化为0。然后,我们进行累加计算,并更新ValueState中的值。最后,我们将累加结果输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

瑟 王

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

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

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

打赏作者

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

抵扣说明:

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

余额充值