Apache flink 在Flink进行检查时,太多计时器花费了太多时间

Apache flink 在Flink进行检查时,太多计时器花费了太多时间,apache-flink,flink-streaming,Apache Flink,Flink Streaming,我使用State和TimeService对大量消息进行滑动计数。滑动尺寸为1,窗口尺寸大于10小时。我遇到的问题是检查点需要花费很多时间。为了提高性能,我们使用了增量检查点。但当系统执行检查点时,速度仍然很慢。我们发现大部分时间用于序列化用于清理数据的计时器。我们每把钥匙都有一个计时器,总共大约有3亿个计时器 任何解决这个问题的建议都将不胜感激。或者我们可以用另一种方法计算? ———————————————————————————————————————————— 我想补充一些情况的细节。滑动大

我使用
State
TimeService
对大量消息进行滑动计数。滑动尺寸为1,窗口尺寸大于10小时。我遇到的问题是检查点需要花费很多时间。为了提高性能,我们使用了增量检查点。但当系统执行检查点时,速度仍然很慢。我们发现大部分时间用于序列化用于清理数据的计时器。我们每把钥匙都有一个计时器,总共大约有3亿个计时器

任何解决这个问题的建议都将不胜感激。或者我们可以用另一种方法计算? ————————————————————————————————————————————
我想补充一些情况的细节。滑动大小是一个事件,窗口大小超过10小时(每秒大约有300个事件),我们需要对每个事件做出反应。所以在这种情况下,我们没有使用Flink提供的窗口。我们使用
键控状态
来存储以前的信息。
定时器
用于
ProcessFunction
触发旧数据的清理作业。最后,dinstinct键的数量非常大。

如果不使用计时器,而是在流的每个元素中添加一个额外字段来存储当前处理时间或到达时间,会怎么样?因此,一旦您想从流中清除旧数据,您只需使用筛选器运算符并检查数据是否为要删除的旧英语。

与其在每个事件上注册清除计时器,不如每一段时间只注册一次计时器,例如每1分钟一次?您只能在第一次看到密钥时注册它,并在
onTimer
中刷新它。例如:

new ProcessFunction<SongEvent, Object>() {

  ...

  @Override
  public void processElement(
      SongEvent songEvent,
      Context context,
      Collector<Object> collector) throws Exception {

    Boolean isTimerRegistered = state.value();
    if (isTimerRegistered != null && !isTimerRegistered) {
      context.timerService().registerProcessingTimeTimer(time);
      state.update(true);
    }

    // Standard processing


  }

  @Override
  public void onTimer(long timestamp, OnTimerContext ctx, Collector<Object> out)
      throws Exception {
    pruneElements(timestamp);

    if (!elements.isEmpty()) {
      ctx.timerService().registerProcessingTimeTimer(time);
    } else {
      state.clear();
    }
  }
}
newprocessfunction(){
...
@凌驾
公共无效处理元素(
SongEvent SongEvent,
语境,
收集器)引发异常{
布尔值=state.value();
if(isTimerRegistered!=null&&!isTimerRegistered){
context.timerService().RegisterProcessingTimer(时间);
state.update(true);
}
//标准处理
}
@凌驾
公用void onTimer(长时间戳、OnTimerContext ctx、收集器输出)
抛出异常{
pruneElements(时间戳);
如果(!elements.isEmpty()){
ctx.timerService().RegisterProcessingTimer(时间);
}否则{
state.clear();
}
}
}

Flink SQL
Over
子句也实现了类似的功能。你可以看一下

我认为这应该可以:

通过有效地执行keyBy(key mod 100000)之类的操作,将Flink使用的密钥数量从300M减少到100K(例如)。然后,ProcessFunction可以使用MapState(其中键是原始键)存储它所需的任何内容

MapState有迭代器,您可以使用迭代器定期对每个映射进行爬网以使旧项过期。坚持每把钥匙只有一个计时器的原则(如果你愿意的话,每个uberkey),这样你就只有100K个计时器

更新:


包括Flink 1.6,它允许异步检查计时器,并将其存储在RocksDB中。这使得Flink应用程序拥有大量计时器更加实用。

您能提供更详细的说明吗?我试着回答你,但是没有更多的细节是很困难的。请澄清情况。滑动尺寸是“一”什么?一小时,一分钟,还是一件事?每个事件分配到多少个不同的窗口中?窗口化与所讨论的计时器有什么关系(您是在谈论flink用于TimeWindow的计时器,还是ProcessFunction中的某些东西)?真的有300米不同的钥匙吗?谢谢你的关注。我为情况补充了一些细节。我希望这能澄清问题。谢谢你的关注。在某些情况下,这可能是一个解决方案,但在我的情况下不是。当此键下没有事件进入时,我无法清除旧数据。我正是以这种方式使用计时器的。一个键(或状态)的计时器。问题是钥匙太多了。非常感谢。我会试试看。我想可能有用!