Flink:如何在另一个流中存储状态和使用?

时间:2016-12-09 15:45:18

标签: apache-flink flink-streaming

我有一个用于Flink的用例,我需要从文件中读取信息,存储每一行​​,然后使用此状态过滤另一个流。

我现在使用connect运算符和RichCoFlatMapFunction完成所有这些操作,但感觉过于复杂。另外,我担心flatMap2可以在从文件加载所有状态之前开始执行:

fileStream
    .connect(partRecordStream.keyBy((KeySelector<PartRecord, String>) partRecord -> partRecord.getPartId()))
    .keyBy((KeySelector<String, String>) partId -> partId, (KeySelector<PartRecord, String>) partRecord -> partRecord.getPartId())
    .flatMap(new RichCoFlatMapFunction<String, PartRecord, PartRecord>() {
        private transient ValueState<String> storedPartId;
        @Override
        public void flatMap1(String partId, Collector<PartRecord> out) throws Exception {
            // store state
            storedPartId.update(partId);
        }

        @Override
        public void flatMap2(PartRecord record, Collector<PartRecord> out) throws Exception {
            if (record.getPartId().equals(storedPartId.value())) {
                out.collect(record);
            } else {
                // do nothing
            }
        }

        @Override
        public void open(Configuration parameters) throws Exception {
            ValueStateDescriptor<String> descriptor =
                    new ValueStateDescriptor<>(
                            "partId", // the state name
                            TypeInformation.of(new TypeHint<String>() {}),
                            null);
            storedPartId = getRuntimeContext().getState(descriptor);
        }
    });

有没有更好的方法(从Flink 1.1.3开始)来实现这种加载状态模式,然后在后续流中使用它?

1 个答案:

答案 0 :(得分:3)

您对CoFlatMapFunction的疑虑是正确的。调用flatMap1flatMap2的顺序无法控制,并且取决于数据到达的顺序。因此,在flatMap2读取所有数据之前,可能会调用flatMap1

Flink 1.1.3在开始处理流之前读取所有数据的唯一方法是使用open()的{​​{1}}方法中的数据,即你必须手动读取和解析文件。

这基本上是广播加入策略,即运营商的每个并行实例都会这样做。缺点是将复制文件的数据。好处是你不必改变“主”流(不需要使用RichFlatMapFunction)。