Apache flink 如何清除非活动键的流状态?

Apache flink 如何清除非活动键的流状态?,apache-flink,flink-streaming,Apache Flink,Flink Streaming,我的目标是有一个Flink流媒体程序来保存最后N个id,其中id是从事件中提取的。接收器是一个Cassandra存储,因此可以随时获取ID列表。重要的是,卡桑德拉在每次事件发生后都会立即更新 这可以通过mapWithState轻松实现(请参见下面的代码)。然而,这段代码有一个重要的问题。状态由userid键控。一些用户可能会活跃一段时间,然后再也不会活跃。我担心的是,状态存储将永远增长 如何清除非活动键的状态 case class MyEvent(userId: Int, id: String)

我的目标是有一个Flink流媒体程序来保存最后N个id,其中id是从事件中提取的。接收器是一个Cassandra存储,因此可以随时获取ID列表。重要的是,卡桑德拉在每次事件发生后都会立即更新

这可以通过
mapWithState
轻松实现(请参见下面的代码)。然而,这段代码有一个重要的问题。状态由
userid
键控。一些用户可能会活跃一段时间,然后再也不会活跃。我担心的是,状态存储将永远增长

如何清除非活动键的状态

case class MyEvent(userId: Int, id: String)

env
  .addSource(new FlinkKafkaConsumer010[MyEvent]("vips", new MyJsonDeserializationSchema(), kafkaConsumerProperties))
  .keyBy(_.userId)
  .mapWithState[(Int, Seq[String]), Seq[String]] { (in: MyEvent, currentIds: Option[Seq[String]]) =>
    val keepNIds = currentIds match {
      case None => Seq(in.id)
      case Some(cids) => (cids :+ in.id).takeRight(100)
    }
    ((in.userId, keepNIds), Some(keepNIds))
  }
  .addSink { in: (Int, Seq[String]) =>
    CassandraSink.appDatabase.idsTable.store(...)
  }

生长状态是一个重要且正确的观察结果。如果您的键空间正在移动,则肯定会发生这种情况


Flink 1.2.0添加了解决此问题的
ProcessFunction
ProcessFunction
类似于
flatmap函数
,但可以访问计时器服务。您可以注册计时器,这些计时器在过期时调用
onTimer()
回调函数。回调可以用来清除状态。

谢谢,现在我找到了
RichProcessFunction
,我可以用
ctx.timerService().registerProcessingTimer(expiryMillis)
这样的代码注册回调。我们希望将这些数据保留很长时间,目前为30天。与此同时,将有数十亿的额外回调。Flink能处理如此大量的回调吗?计时器处于状态并被检查。我认为这应该是可能的,但我建议在一些负载下进行测试。我找到了一种方法,将每个键的计时器数量限制为1个:
processElement
仅为新键启动计时器,并且
onTimer
在最新和当前状态尚未过期时再次安排计时器。现在我们只能得到几千万个活动计时器。我希望这能奏效:)嗨@Erikvanosten,你介意提供更多关于你是如何做到这一点的信息吗?或者共享一点代码?请我正在尝试做一些类似的事情,但到目前为止没有太大的成功。@Erikvanosten我支持这一点,你能给我们一些更多的信息吗