Apache flink 弗林克:如何存储状态并在另一个流中使用?
我有一个Flink的用例,我需要从文件中读取信息,存储每一行,然后使用这个状态过滤另一个流 我现在使用Apache flink 弗林克:如何存储状态并在另一个流中使用?,apache-flink,flink-streaming,Apache Flink,Flink Streaming,我有一个Flink的用例,我需要从文件中读取信息,存储每一行,然后使用这个状态过滤另一个流 我现在使用connect操作符和RichCoFlatMapFunction完成了所有这些工作,但感觉太复杂了。此外,我担心flatmap 2可能在从文件加载所有状态之前开始执行: fileStream .connect(partRecordStream.keyBy((KeySelector<PartRecord, String>) partRecord -> partRecord
connect
操作符和RichCoFlatMapFunction
完成了所有这些工作,但感觉太复杂了。此外,我担心flatmap 2
可能在从文件加载所有状态之前开始执行:
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);
}
});
fileStream
.connect(partRecordStream.keyBy((KeySelector)partRecord->partRecord.getPartId())
.keyBy((KeySelector)partId->partId,(KeySelector)partRecord->partRecord.getPartId())
.flatMap(新的RichCoFlatMapFunction(){
私有瞬态值状态存储部分;
@凌驾
public void flatMap1(字符串partId,收集器out)引发异常{
//存储状态
存储的partId.update(partId);
}
@凌驾
公共void flatMap2(PartRecord记录,收集器输出)引发异常{
if(record.getPartId().equals(storedPartId.value())){
取出、收集(记录);
}否则{
//无所事事
}
}
@凌驾
公共void open(配置参数)引发异常{
ValueStateDescriptor描述符=
新的ValueStateDescriptor(
“partId”,//状态名称
TypeInformation.of(新的TypeHint(){}),
无效);
storedPartId=getRuntimeContext().getState(描述符);
}
});
是否有更好的方法(从Flink 1.1.3开始)来完成这种加载状态模式,然后在后续流中使用它?您对
CoFlatMapFunction
的担忧是正确的。调用flatmap 1
和flatmap 2
的顺序无法控制,并且取决于数据到达的顺序。因此,flatmap 1
读取所有数据之前,可能会调用flatmap 2
在Flink 1.1.3中,在开始处理流之前读取所有数据的唯一方法是使用RichFlatMapFunction
的open()
方法中的数据,即,您必须手动读取和解析文件
这基本上是一种广播连接策略,即,操作符的每个并行实例都将执行此操作。缺点是文件的数据将被复制。这样做的好处是,您不必洗牌“主”流(无需使用
keyBy()
)。啊,我明白了。因此,我可以在open()
方法中解析文件,但只要我不使用keyBy()
上游,就只有一个操作符实例。但是,这实际上是一个串行操作,对吗?FlatMap
操作符也可以并行运行,而无需调用keyBy()
。您只需指定运算符的并行性。但是,数据将随机分布在并行线程中keyBy
将对数据进行哈希分区。如果有多个FlatMap
操作符,则每个操作符都会读取文件并保存状态。因此,您有冗余的IO和内存使用,但操作员将并行运行。@FabianHueske按照这种方法,每次更新文件时,都需要重新启动作业以获取更新的内容。在flink中是否有一种方法,在文件状态可用之前不处理主流记录。基本上我们可以设置元素的处理顺序。