在WindowAssigner
中,元素被分配给一个或多个TimeWindow
个实例。如果是滑动事件时间窗口,则会发生在SlidingEventTimeWindows#assignWindows
1 中。
如果是包含size=5
和slide=1
的窗口,则timestamp=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有一个时间的开始和之前,没有窗户?如果没有,从哪里开始寻找改变呢?在上述情况下,Flink应该只有一个窗口(t=[4,8[ Window 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个Windows中。
脚注:
org.apache.flink.streaming.api.windowing.assigners.SlidingEventTimeWindows#assignWindows
答案 0 :(得分:2)
目前无法指定Flink作业的有效时间间隔。考虑到您可能也希望将您的工作应用于历史数据,这可能也会有点问题。
但是,你可以做的是过滤手动开始时间之前开始的窗口:
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
val startTime = 1
val windowLength = 2
val slide = 1
val input = env.fromElements((1,1), (2,2), (3,3))
.assignAscendingTimestamps(x => x._2)
val windowed = input
.timeWindowAll(Time.milliseconds(windowLength), Time.milliseconds(slide))
.apply{ (window, iterable, collector: Collector[Int]) =>
if (window.getStart >= startTime) {
collector.collect(iterable.map(_._1).reduce(_ + _))
} else {
// discard early windows
}
}
windowed.print()
env.execute()
答案 1 :(得分:0)
我可能会为此问题找到更好的解决方法。
我们的想法是将水印设置到将来足够远的地方,以便为您的窗口提供足够的数据。早期的窗户仍然存在,但它们将被丢弃。
以下是AssignerWithPeriodicWatermarks[T]
的概念证明:
class WMG[T](wait: Long) extends AssignerWithPeriodicWatermarks[T] {
var t: Option[Long] = None
var firstTime = true
override def extractTimestamp(el: T, prevTs: Long): Long = {
t = Some(prevTs)
prevTs
}
override def getCurrentWatermark(): Watermark = (t, firstTime) match {
case (None, _) => return null
case (Some(v), false) => new Watermark(v)
case (Some(v), true) => {
firstTime = false
new Watermark(v + wait)
}
}
}
<德尔>
`wait`是你第一个窗口的大小。
似乎工作正常,但我不明白眨眼足以确定。
德尔>
更新:不幸的是,它不起作用(现在我不知道为什么会这样),键入流中的键总是很少有&#34;早期的窗口和&#34; #34 ;.所以最后我只是用以下内容过滤错误的窗口:
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))
})