Apache flink Flink可重缩放键控流状态函数

Apache flink Flink可重缩放键控流状态函数,apache-flink,flink-streaming,Apache Flink,Flink Streaming,我有一个Flink的工作,我尝试在后端类型RockDB中使用键控流状态函数(MapState) environment .addSource(consumer).name("MyKafkaSource").uid("kafka-id") .flatMap(pojoMapper).name("MyMapFunction").uid("map-id") .keyBy(new MyKeyExtractor()) .map(new MyRichMapFunction()).name("MyRichMap

我有一个Flink的工作,我尝试在后端类型RockDB中使用键控流状态函数(MapState)

environment
.addSource(consumer).name("MyKafkaSource").uid("kafka-id")
.flatMap(pojoMapper).name("MyMapFunction").uid("map-id")
.keyBy(new MyKeyExtractor())
.map(new MyRichMapFunction()).name("MyRichMapFunction").uid("rich-map-id")
.addSink(sink).name("MyFileSink").uid("sink-id")
MyRichMapFunction是一个有状态函数,它扩展了RichMapFunction,RichMapFunction有以下代码:

public static class MyRichMapFunction extends RichMapFunction<MyEvent, MyEvent> {
    private transient MapState<String, Boolean> cache;
    @Override
    public void open(Configuration config) {
        MapStateDescriptor<String, Boolean> descriptor =
                new MapStateDescriptor("seen-values", TypeInformation.of(new TypeHint<String>() {}), TypeInformation.of(new TypeHint<Boolean>() {}));
        cache = getRuntimeContext().getMapState(descriptor);
    }
    @Override
    public MyEvent map(MyEvent value) throws Exception {
        if (cache.contains(value.getEventId())) {
            value.setIsSeenAlready(Boolean.TRUE);
            return value;
        }
        value.setIsSeenAlready(Boolean.FALSE);
        cache.put(value.getEventId(), Boolean.TRUE)
        return value;
    }
}
公共静态类MyRichMapFunction扩展了RichMapFunction{
私有状态缓存;
@凌驾
公共无效打开(配置){
MapStateDescriptor描述符=
新的MapStateDescriptor(“看到的值”,TypeInformation.of(new TypeHint(){}),TypeInformation.of(new TypeHint(){});
cache=getRuntimeContext().getMapState(描述符);
}
@凌驾
公共MyEvent映射(MyEvent值)引发异常{
if(cache.contains(value.getEventId())){
value.setisseeneready(Boolean.TRUE);
返回值;
}
value.setisseeneready(Boolean.FALSE);
cache.put(value.getEventId(),Boolean.TRUE)
返回值;
}
}

将来,我想重新调整并行度(从2到4),所以我的问题是,如何实现可重新缩放的键控状态,以便在更改并行度后,我可以将相应的缓存键控数据获取到其相应的任务槽中。我试图探索这一点,在那里我找到了一份文档。据此,可以通过使用ListCheckPointed接口实现可重新伸缩的操作员状态,该接口提供了快照状态/恢复状态方法。但不确定如何实现可重新伸缩的键控状态(MyRichMapFunction)?我是否需要为MyRichMapFunction类实现ListCheckPointed接口?如果是,我如何根据restoreState方法上的新并行密钥哈希重新分配缓存(我的MapState将在启用TTL的情况下保存大量密钥,假设在任何时间点最多可保存10亿个密钥)?有人能帮我一下吗?或者如果你能给我举个例子,那也不错。

你写的代码已经可以重新缩放了;Flink的托管键控状态可以通过设计进行重新缩放。通过重新平衡对实例的键分配,可以重新调整键控状态。(您可以将键控状态视为分片键/值存储。从技术上讲,所发生的是使用一致哈希将键映射到键组,并且每个并行实例负责一些键组。重新缩放只涉及在实例之间重新分配键组。)

ListCheckpointed
接口用于非键控上下文中使用的状态,因此它不适合您所做的操作。还要注意的是,Flink 1.11中的
ListCheckpointed
将被弃用,取而代之的是更通用的
CheckpointedFunction

还有一件事:如果
MyKeyExtractor
是通过
value.getEventId()
进行键控,那么您可以对缓存使用
ValueState
,而不是
MapState
。这是因为对于键控状态,每个键都有一个单独的ValueState值。仅当需要为流中的每个键存储多个属性/值对时,才需要使用MapState


在下的Flink文档中讨论了其中的大部分内容,其中包括非常接近您正在做的事情。

哦,如果我使用托管状态,那么我就不需要考虑重新缩放,默认情况下,当我更改并行性时,Flink会提供这样的功能,对吗?我对他们使用CheckpointedAsynchronous功能的示例非常困惑,所以如果我理解正确的话,GitHub示例是非托管状态,所以他们明确地处理了CheckpointedAsynchronously方法,对吗?(顺便说一句,谢谢你的提示ValueState)是的,没错。仅供参考,你发现的这个例子很古老,从那时起,正确的做事方式已经改变了。事实上,CheckpointedAsynchronous已经不存在了。像往常一样,我接受了答案,但由于声誉不好,我没有投赞成票:)