Flink是否支持BroadcastState的状态TTL?

时间:2019-08-09 06:38:52

标签: apache-flink

对于Flink 1.8.1,我试图将State TTL应用于BroadcastState(使用MapStateDescriptor),如下所示:

(Holder是一个包装私有int变量“ deger”的POJO)

...

        StreamExecutionEnvironment envStream = StreamExecutionEnvironment.getExecutionEnvironment();
        StateBackend stateBackend = new FsStateBackend("file://.....");
        envStream.setStateBackend(stateBackend);
        envStream.enableCheckpointing(1_000L, CheckpointingMode.EXACTLY_ONCE);

...

        MapStateDescriptor<Integer, Client> clientMapStateDescriptor = new MapStateDescriptor<>(
            "ClientBroadcastState",
            BasicTypeInfo.INT_TYPE_INFO,
            TypeInformation.of(new TypeHint<Client>() {})
        );
        StateTtlConfig ttlConfig = StateTtlConfig
            .newBuilder(Time.seconds(3))
            // .cleanupFullSnapshot()
            // .cleanupInBackground()
            .cleanupIncrementally(100, false)
            .setUpdateType(StateTtlConfig.UpdateType.OnCreateAndWrite)
            .setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired)
            .build();
        clientMapStateDescriptor.enableTimeToLive(ttlConfig);

        DataStream<Client> clientDataStream = envStream.fromCollection(clientList);
        // clientDataStream.print("clientDataStream");

        BroadcastStream<Client> clientBroadcastStream = clientDataStream
            .broadcast(clientMapStateDescriptor);

        List<Holder> holderList = new ArrayList<>(count);
        for(int i = 0; i < count; i++) {
            holderList.add(new Holder(i));
        }
        DataStream<Holder> integerHolderDataStream = envStream.fromCollection(holderList);

        BroadcastConnectedStream<Holder, Client> connectedStreams = integerHolderDataStream
            .keyBy("deger")
            .connect(clientBroadcastStream);

        SingleOutputStreamOperator<Row> operator = connectedStreams.process(new KeyedBroadcastProcessFunction<Integer, Holder, Client, Row>() {

            @Override
            public void processElement(Holder value, ReadOnlyContext ctx, Collector<Row> out) throws Exception {
                for (Map.Entry<Integer, Client> entry : ctx.getBroadcastState(clientMapStateDescriptor).immutableEntries()) {
                    Client c = ctx.getBroadcastState(clientMapStateDescriptor).get(entry.getKey());
                    System.out.println(value.getDeger() + " - " + c);
                }
                Thread.sleep(1000L);
            }

            @Override
            public void processBroadcastElement(Client value, Context ctx, Collector<Row> out) throws Exception {
                ctx.getBroadcastState(clientMapStateDescriptor).put(value.getId(), value);
            }

        });

...

holderList有足够的实例来测试状态项是否被驱逐。

但是BroadcastState中的条目不会过期。

我尝试过的事情:

  • 使用其他状态后端(FsStateBackend
  • 启用检查点
  • 明确访问地图状态值

我可能做错了什么? BroadcastState是否支持StateTTL?

如果没有,您能否提供一个示例(如何使用MapStateDescriptor)将广播状态中的条目逐出?

1 个答案:

答案 0 :(得分:0)

根据FLIP-25中的内容,StateTTL仅用于键控状态。

只能在BroadcastProcessFunction(或Keyed BroadcastProcessFunction)的processBroadcastElement方法中写入或清除存储在BroadcastState中的项目-这意味着您必须在处理接收另一个广播元素的过程中执行此操作。而且,您需要注意在所有并行实例中使用完全相同的逻辑,因为Flink期望每个实例在BroadcastState的内容上都是一致的,如果您在此处进行不确定性或特定于实例的操作,可能会导致奇怪的事情。

一种解决方案是广播流记录,接收者将其解释为使较早记录从广播状态过期的命令。