【问题标题】:Checkpoints increasing over time in FlinkFlink 中的检查点随时间增加
【发布时间】:2020-09-09 06:36:48
【问题描述】:

聚合到this question 我仍然不清楚为什么我的 Flink 作业的检查点会随着时间的推移而增长,而目前,在运行大约 7 天的时间里,这些检查点从未达到稳定状态。 我目前使用的是 Flink 1.10 版本,FS State Backend 作为我的工作无法承受使用 RocksDB 的延迟成本。

查看检查点在 7 天内的演变: 假设我在我的所有有状态操作符中的状态 TTL 配置为一小时或更长,在一种情况下为一天:

public static final StateTtlConfig ttlConfig = StateTtlConfig.newBuilder(Time.hours(1))
            .setUpdateType(StateTtlConfig.UpdateType.OnCreateAndWrite)
            .setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired)
            .cleanupFullSnapshot().build();

在我看来,所有进入状态的对象都将在过期时间后被清理,因此应该减少检查点的大小,并且我们预计每天的数据量或多或少相同。

另一方面,我们有一条流量曲线,它在一天中的几个小时内有更多的传入数据,但深夜流量下降,所有进入过期状态的对象都应该被清理,导致检查点大小应该减少而不是保持相同的大小,直到流量再次上升。

让我们看一下这个用例的代码示例:

DataStream<Event> stream = addSource(source);
KeyedStream<Event, String> keyedStream = stream.filter((FilterFunction<Event>) event ->
                    apply filters here;))
                    .name("Events filtered")
                    .keyBy(k -> k.rType.equals("something") ? k.id1 : k.id2);
keyedStream.flatMap(new MyFlatMapFunction())


public class MyFlatMapFunction extends RichFlatMapFunction<Event, Event>{
private final MapStateDescriptor<String, Event> descriptor = new MapStateDescriptor<>("prev_state", String.class, Event.class);
private MapState<String, Event> previousState;

@Override
    public void open(Configuration parameters) {
        /*ttlConfig described above*/
        descriptor.enableTimeToLive(ttlConfig);
        previousState = getRuntimeContext().getMapState(descriptor);
    }

@Override
    public void flatMap(Event event, Collector<Event> collector) throws Exception {
      final String key = event.rType.equals("something") ? event.id1 : event.id2;
      Event previous = previousState.get(key);
      if(previous != null){
        /*something done here*/
      }else /*something done here*/
        previousState.put(key, previous);
        collector.collect(previous);
 }
}

这些或多或少是用例的结构,还有一些使用 Windows(时间窗口或会话窗口)的结构

问题:

  • 我在这里做错了什么?
  • 状态是否在到期时被清理,这种情况与其余用例相同吗?
  • 如果检查点工作不正常,有什么办法可以帮助我修复检查点的大小?
  • 这种行为正常吗?

亲切的问候!

【问题讨论】:

  • JVM 堆是否也以类似的方式增长,或者只是检查点的大小?
  • 不,JVM 堆没问题。这意味着 GC 正在按预期工作,对吗?谢谢。
  • 我无法为您的应用制定一个理论来解释您分享的所有事实。有些东西没有加起来。鉴于我不太了解情况,因此我不愿提供任何建议。
  • 您可以进行一项实验,这可能会揭示检查点规模不断扩大的情况。如果您从检查点恢复(副本)作业,并禁用输入,则一小时后检查点大小应降至零。
  • 允许我再问你一个问题:我的工作是从 RabbitMQ -> Transformations -> Sink 读取事件,我没有使用重启策略,因为如果我的工作失败,SVC 服务将管理自动重新启动作业,它将从头开始。从这种操作模式开始,检查点对我来说毫无意义,因为它们不习惯在失败的情况下重新启动,根据我的理解,如果 Flink 应用程序崩溃然后从检查点重新启动,它们是值得的,但是因为我的工作总是开始从头开始:我的场景中是否需要检查点?

标签: apache-flink flink-streaming flink-cep


【解决方案1】:

在这段代码中,您似乎只是在写回已经存在的状态,这仅用于重置 TTL 计时器。这可以解释为什么状态没有过期。

Event previous = previousState.get(key);
if (previous != null) {
  /*something done here*/
} else
  previousState.put(key, previous);

看来您应该使用ValueState 而不是MapState。 ValueState 有效地提供了一个分片键/值存储,其中键是用于在 keyBy 中对流进行分区的键。 MapState 为您提供每个键的嵌套映射,而不是单个值。但是,由于您在 flatMap 中使用的键与您最初用于对流进行键控的键相同,因此键分区的 ValueState 似乎就是您所需要的。

【讨论】:

  • 非常感谢大卫。这个答案向我澄清了一切。亲切的问候
  • 允许我再问一件与此相关的事情:与永不过期的值相同的问题可能是 CPU 负载的根源随着时间的推移随着检查点的增加而增加?因为它会导致 CPU 花费更多精力来完成检查点?再次感谢。
  • 一般来说,状态后端可能会花时间尝试使没有过期的东西过期,不仅仅是在检查点期间,而是持续不断。但如果键空间在增长,我希望看到堆增长。
  • @DavidAnderson 我正在使用 flink 1.10 和 RocksDb 作为状态后端,我观察到类似的检查点大小图在运行几天后逐渐增加(基于给定的总 flink TM 内存)作业重新启动随着堆使用量的显着增加,这是正常行为吗?
  • 对于 RocksDB,检查点大小逐渐增加是正常的,直到 RocksDB 触发压缩。根据您的数据量和更新频率,这可能需要很长时间。至于拥有大堆,我不希望使用 RocksDB,但肯定有可能——这取决于你的工作是做什么的,以及它是如何配置的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多