Apache flink Flink获取KeyedState状态值并在另一个流中使用

Apache flink Flink获取KeyedState状态值并在另一个流中使用,apache-flink,flink-streaming,Apache Flink,Flink Streaming,我知道键控状态属于its键,只有当前键访问其状态值,其他键无法访问不同键的状态值 我尝试使用相同的密钥访问状态,但使用不同的流。可能吗 如果这是不可能的,那么我将有2个重复的数据 不是:我需要两个流,因为它们每个都有不同的时间窗口和不同的实现 下面是一个示例(我知道keyBy(sommething)对于两个流操作都是相同的): 公共类示例{ streamA .凯比(某物) .时间窗口(时间.秒(4)) .process(新的CustomMyProcessFunction()) .name(“Cu

我知道键控状态属于its键,只有当前键访问其状态值,其他键无法访问不同键的状态值

我尝试使用相同的密钥访问状态,但使用不同的流。可能吗

如果这是不可能的,那么我将有2个重复的数据

不是:我需要两个流,因为它们每个都有不同的时间窗口和不同的实现

下面是一个示例(我知道keyBy(sommething)对于两个流操作都是相同的):

公共类示例{
streamA
.凯比(某物)
.时间窗口(时间.秒(4))
.process(新的CustomMyProcessFunction())
.name(“CustomMyProcessFunction”)
.print();
streamA
.凯比(某物)
.时间窗口(时间.秒(1))
.process(新的CustomMyAnotherProcessFunction())
.name(“CustomMyProcessFunction”)
.print();
}
公共类CustomMyProcessFunction扩展了ProcessWindowFunction
{
私有记录器Logger=LoggerFactory.getLogger(CustomMyProcessFunction.class);
私有瞬时值状态simpleEntityValueState;
私人单纯单纯单纯;
@凌驾
公共void open(配置参数)引发异常
{
ValueStateDescriptor simpleEntityValueStateDescriptor=新的ValueStateDescriptor(
“样本”,
TypeInformation.of(simplentity.class)
);
simpleEntityValueState=getRuntimeContext().getState(simpleEntityValueStateDescriptor);
}
@凌驾
公共无效进程(…)引发异常
{
SimpleEntityValue=simpleEntityValueState.value();
如果(值==null)
{
SimpleEntity newVal=新SimpleEntity(“样本”);
logger.info(“新价值出售”);
simplentityvaluestate.update(newVal);
}
...
}
...
}
公共类CustomMyAnotherProcessFunction扩展ProcessWindowFunction
{
私有瞬时值状态simpleEntityValueState;
@凌驾
公共void open(配置参数)引发异常
{
ValueStateDescriptor simpleEntityValueStateDescriptor=新的ValueStateDescriptor(
“样本”,
TypeInformation.of(simplentity.class)
);
simpleEntityValueState=getRuntimeContext().getState(simpleEntityValueStateDescriptor);
}
@凌驾
公共无效进程(…)引发异常
{
SimpleEntityValue=simpleEntityValueState.value();
if(值!=null)
logger.info(value.toString());//我希望是SimpleEntity(“示例”)
取出。收集(…);
}
...
}

我尝试了你的想法,用同一个键在两个操作符之间共享状态

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.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.source.SourceFunction;
import org.apache.flink.streaming.api.functions.windowing.ProcessWindowFunction;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.streaming.api.windowing.windows.TimeWindow;
import org.apache.flink.util.Collector;

import java.io.IOException;

public class FlinkReuseState {

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

        DataStream<Integer> stream1 = env.addSource(new SourceFunction<Integer>() {
            @Override
            public void run(SourceContext<Integer> sourceContext) throws Exception {
                int i = 0;
                while (true) {
                    sourceContext.collect(1);
                    Thread.sleep(1000);
                }
            }

            @Override
            public void cancel() {

            }
        });

        DataStream<Integer> stream2 = env.addSource(new SourceFunction<Integer>() {
            @Override
            public void run(SourceContext<Integer> sourceContext) throws Exception {
                while (true) {
                    sourceContext.collect(1);
                    Thread.sleep(1000);
                }
            }

            @Override
            public void cancel() {

            }
        });


        DataStream<Integer> windowedStream1 = stream1.keyBy(Integer::intValue)
                .timeWindow(Time.seconds(3))
                .process(new ProcessWindowFunction<Integer, Integer, Integer, TimeWindow>() {
                    private ValueState<Integer> value;

                    @Override
                    public void open(Configuration parameters) throws Exception {
                        super.open(parameters);
                        ValueStateDescriptor<Integer> desc = new ValueStateDescriptor<Integer>("value", Integer.class);
                        value = getRuntimeContext().getState(desc);
                    }

                    @Override
                    public void process(Integer integer, Context context, Iterable<Integer> iterable, Collector<Integer> collector) throws Exception {
                        iterable.forEach(x -> {
                            try {
                                if (value.value() == null) {
                                    value.update(1);
                                } else {
                                    value.update(value.value() + 1);
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        });
                        collector.collect(value.value());
                    }
                });

        DataStream<String> windowedStream2 = stream2.keyBy(Integer::intValue)
                .timeWindow(Time.seconds(3))
                .process(new ProcessWindowFunction<Integer, String, Integer, TimeWindow>() {

                    private ValueState<Integer> value;

                    @Override
                    public void open(Configuration parameters) throws Exception {
                        super.open(parameters);
                        ValueStateDescriptor<Integer> desc = new ValueStateDescriptor<Integer>("value", Integer.class);
                        value = getRuntimeContext().getState(desc);
                    }

                    @Override
                    public void process(Integer s, Context context, Iterable<Integer> iterable, Collector<String> collector) throws Exception {
                        iterable.forEach(x -> {
                            try {
                                if (value.value() == null) {
                                    value.update(1);
                                } else {
                                    value.update(value.value() + 1);
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        });
                        collector.collect(String.valueOf(value.value()));
                    }
                });

        windowedStream2.print();

        windowedStream1.print();

        env.execute();

    }
}

根据官方文档,*每个键控状态在逻辑上绑定到一个唯一的
组合,由于每个键“属于”一个键控操作符的一个并行实例,我们可以简单地将其视为
*

我认为不可能通过给不同运营商的州起相同的名字来共享州


你试过协处理函数吗?这样,您还可以为每个流实现两个进程函数,唯一的问题是时间窗口。您能提供有关流程逻辑的更多详细信息吗?

我尝试了您的想法,使用同一个键在两个操作员之间共享状态

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.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.source.SourceFunction;
import org.apache.flink.streaming.api.functions.windowing.ProcessWindowFunction;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.streaming.api.windowing.windows.TimeWindow;
import org.apache.flink.util.Collector;

import java.io.IOException;

public class FlinkReuseState {

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

        DataStream<Integer> stream1 = env.addSource(new SourceFunction<Integer>() {
            @Override
            public void run(SourceContext<Integer> sourceContext) throws Exception {
                int i = 0;
                while (true) {
                    sourceContext.collect(1);
                    Thread.sleep(1000);
                }
            }

            @Override
            public void cancel() {

            }
        });

        DataStream<Integer> stream2 = env.addSource(new SourceFunction<Integer>() {
            @Override
            public void run(SourceContext<Integer> sourceContext) throws Exception {
                while (true) {
                    sourceContext.collect(1);
                    Thread.sleep(1000);
                }
            }

            @Override
            public void cancel() {

            }
        });


        DataStream<Integer> windowedStream1 = stream1.keyBy(Integer::intValue)
                .timeWindow(Time.seconds(3))
                .process(new ProcessWindowFunction<Integer, Integer, Integer, TimeWindow>() {
                    private ValueState<Integer> value;

                    @Override
                    public void open(Configuration parameters) throws Exception {
                        super.open(parameters);
                        ValueStateDescriptor<Integer> desc = new ValueStateDescriptor<Integer>("value", Integer.class);
                        value = getRuntimeContext().getState(desc);
                    }

                    @Override
                    public void process(Integer integer, Context context, Iterable<Integer> iterable, Collector<Integer> collector) throws Exception {
                        iterable.forEach(x -> {
                            try {
                                if (value.value() == null) {
                                    value.update(1);
                                } else {
                                    value.update(value.value() + 1);
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        });
                        collector.collect(value.value());
                    }
                });

        DataStream<String> windowedStream2 = stream2.keyBy(Integer::intValue)
                .timeWindow(Time.seconds(3))
                .process(new ProcessWindowFunction<Integer, String, Integer, TimeWindow>() {

                    private ValueState<Integer> value;

                    @Override
                    public void open(Configuration parameters) throws Exception {
                        super.open(parameters);
                        ValueStateDescriptor<Integer> desc = new ValueStateDescriptor<Integer>("value", Integer.class);
                        value = getRuntimeContext().getState(desc);
                    }

                    @Override
                    public void process(Integer s, Context context, Iterable<Integer> iterable, Collector<String> collector) throws Exception {
                        iterable.forEach(x -> {
                            try {
                                if (value.value() == null) {
                                    value.update(1);
                                } else {
                                    value.update(value.value() + 1);
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        });
                        collector.collect(String.valueOf(value.value()));
                    }
                });

        windowedStream2.print();

        windowedStream1.print();

        env.execute();

    }
}

根据官方文档,*每个键控状态在逻辑上绑定到一个唯一的
组合,由于每个键“属于”一个键控操作符的一个并行实例,我们可以简单地将其视为
*

我认为不可能通过给不同运营商的州起相同的名字来共享州


你试过协处理函数吗?这样,您还可以为每个流实现两个进程函数,唯一的问题是时间窗口。您能提供有关流程逻辑的更多详细信息吗?

如前所述,状态始终是单个操作员实例的本地状态。它不能被共享


但是,您可以做的是将状态更新从持有状态的操作员流式传输到需要它的其他操作员。使用,您可以创建复杂的数据流,而无需共享状态。

如前所述,状态始终是单个运算符实例的本地状态。它不能被共享


但是,您可以做的是将状态更新从持有状态的操作员流式传输到需要它的其他操作员。使用,您可以创建复杂的数据流,而无需共享状态。

为什么您不能将状态作为映射操作的一部分返回,并且该流可以用于连接到其他流

为什么您不能将状态作为映射操作的一部分返回,并且该流可以用于连接到其他流

感谢您的简单回答,我不关心
操作员
。我的目标是删除重复状态操作,例如在运算符1中计数后,我将检查另一个运算符2,如果计数器超过阈值,我将不运行运算符2的逻辑等。感谢您的简单回答,我不关心
运算符
。我的目标是删除重复状态操作,例如在运算符1中计数后,我将检查另一个运算符2,如果计数器超过阈值,我将不运行运算符2的逻辑等。。