Flink可重缩放键控流有状态功能

时间:2020-05-04 21:18:09

标签: 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("MyRichMapFunction").uid("rich-map-id")
.addSink(sink).name("MyFileSink").uid("sink-id")

MyRichMapFunction是一个有状态函数,它扩展了具有以下代码的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;
    }
}

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

1 个答案:

答案 0 :(得分:3)

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

ListCheckpointed接口用于非键上下文中使用的状态,因此不适用于您正在做的事情。另请注意,在Flink 1.11中将不推荐使用ListCheckpointed,而推荐使用更通用的CheckpointedFunction

另一件事:如果MyKeyExtractorvalue.getEventId()键控,那么您可能将ValueState<Boolean>用于缓存,而不是MapState<String, Boolean>。之所以可行,是因为对于键控状态,每个键都有一个单独的ValueState值。仅在需要为流中的每个键存储多个属性/值对时,才需要使用MapState。

其中的大多数内容都在Hands-on Training下的Flink文档中进行了讨论,其中包括an example,与您的工作非常接近。