Apache flink ApacheFlink:窗口函数和时间的开始
在Apache flink ApacheFlink:窗口函数和时间的开始,apache-flink,flink-streaming,Apache Flink,Flink Streaming,在WindowAssigner中,一个元素被分配给一个或多个TimeWindow实例。在滑动事件时间窗口的情况下,这发生在SlidingEventTimeWindows#assignWindows1中 如果窗口的大小=5和幻灯片=1,则将时间戳=0的元素分配到以下窗口: 窗口(开始=0,结束=5) 窗口(开始=-1,结束=4) 窗口(开始=-2,结束=3) 窗口(开始=-3,结束=2) 窗口(开始=-4,结束=1) 在一幅图片中: +-&g
WindowAssigner
中,一个元素被分配给一个或多个TimeWindow
实例。在滑动事件时间窗口的情况下,这发生在SlidingEventTimeWindows#assignWindows
1中
如果窗口的大小=5
和幻灯片=1
,则将时间戳=0
的元素分配到以下窗口:
+-> Beginning of time
|
|
+----------------------------------------------+
| size = 5 +--+ element |
| slide = 1 | |
| v |
| t=[ 0,5[ Window 1 XXXXX |
| t=[-1,4[ Window 2 XXXXX |
| t=[-2,3[ Window 3 XXXXX |
| t=[-3,2[ Window 4 XXXXX |
| t=[-4,1[ Window 5 XXXXX |
| |
| time(-4 to +4) ---- |
| 432101234 |
+---------------------------+------------------+
|
|
|
+
有没有办法告诉弗林克,时间是有开始的,在这之前,没有窗户?如果没有,从何处开始更改?在上述情况下,Flink对于第一个元素应该只有一个窗口(t=[4,8[窗口1
)。如下所示:
+-> Beginning of time
|
|
+-----------------------------------------------+
| size = 5 +--+ element |
| slide = 1 | |
| v |
| t=[ 0,5[ Window 1 XXXXX |
| t=[ 1,6[ Window 2 XXXXX |
| t=[ 2,7[ Window 3 XXXXX |
| t=[ 3,8[ Window 4 XXXXX |
| t=[ 4,9[ Window 5 XXXXX |
| |
| time(-4 to +8) ---- |
| 4321012345678 |
+---------------------------+-------------------+
|
|
|
+
一旦窗口数量达到并超过窗口大小,这将不再有效。然后,在上述情况下,所有元素都在5个窗口内
脚注:
org.apache.flink.streaming.api.windowing.assigners.SlidingEventTimeWindows#assignWindows
目前无法指定Flink作业的有效时间间隔。考虑到您可能也想将作业应用于历史数据,这也可能有点问题 但是,您可以手动筛选在超时开始之前启动的窗口:
val env=StreamExecutionEnvironment.getExecutionEnvironment
环境setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
val startTime=1
val windowLength=2
瓦尔幻灯片=1
val input=env.fromElements((1,1)、(2,2)、(3,3))
.分配AscendingTimeStamps(x=>x._2)
val加窗=输入
.timeWindowAll(时间.毫秒(窗口长度),时间.毫秒(幻灯片))
.apply{(窗口,iterable,收集器:收集器[Int])=>
如果(window.getStart>=startTime){
collector.collect(iterable.map(u._1).reduce(u+u))
}否则{
//丢弃早期窗口
}
}
windowed.print()
env.execute()
我可能会为这个问题找到更好的解决方法。
我们的想法是将水印设置在未来足够远的地方,以便为您的窗口提供足够的数据。早期的窗口仍然存在,但它们将被丢弃
以下是具有周期性水印[T]的赋值器的概念证明:
`wait`是您第一个窗口的大小。
似乎工作正常,但我对弗林克的理解还不够肯定。
更新:不幸的是,它不起作用(现在我不知道为什么要这样做),在带有“早期窗口”的密钥流中总是很少有密钥。因此,最后我只是用类似以下内容过滤错误的窗口:
val s = (winSize/winStep).intValue
kstream.flatMapWithState((in: StreamOut, state: Option[Int]) =>
state match {
case None => (Seq(), Some(1))
case Some(s) => (Seq(in), Some(s))
case Some(v) => (Seq(), Some(v+1))
})
作为一种“变通方法”,这种方法目前还可以。我想这种请求并不流行:)这种解决方案甚至可能无法作为变通方法使用,因为您可能需要从流中读取
startTime
(如果是事件时间)。而且在您自己的WindowAssigner
中似乎没有简单的方法来实现这一点,因为没有简单的方法(或者我没有找到任何方法)来存储您读取的第一个元素的时间,而分配者可以访问该方法。
val s = (winSize/winStep).intValue
kstream.flatMapWithState((in: StreamOut, state: Option[Int]) =>
state match {
case None => (Seq(), Some(1))
case Some(s) => (Seq(in), Some(s))
case Some(v) => (Seq(), Some(v+1))
})