Apache Flink(以下简称 Flink) 是一个天然支持无限流数据处理的分布式计算框架,在 Flink 中 Window 可以将无限流切分成有限流,是处理有限流的核心组件,现在Flink 中 Window 可以是时间驱动的(Time Window),也可以是数据驱动的(Count Window)。
Flink提供了几种通用的 WindowAssigner:tumbling window(窗口间的元素无重复),sliding window(窗口间的元素可能重复), session window 以及 global window。
session window(会话窗口):一段持续时间内的元素为一个窗口,超过时间间隙的归到另一个窗口。比如我们在浏览器上登录访问某网站,会分配一个session,session在有效期内可以持续访问,当超过有效期需要重新登录,session就相当于一个窗口。
通过官方示例:org.apache.flink.streaming.examples.windowing.SessionWindowing 进行分析,这个示例根据key进行分组求和。我对这个demo的数据修改了下
加了条(a,1,2)数据,其它都没有改变,数据第一列是key,第二列是时间,第三列是值。运行输出结果如下:
新加的(a,1,2)数据缺失了,为什么输出的结果会是这样的,session window触发条件是什么样的,是怎么执行的。我开始执行这个demo也是一脸蒙圈,调试代码才弄清。下面我们一步步根据源码分析数据的执行过程,结果是如何产生的。
window 主要的操作逻辑在 WindowOperator 类 processElement方法中
1. 第一条数据(a,1,1)进来,分配一个窗口[1,4), 在EventTimeSessionWindows 类中可以看到实现如下:
判断窗口和数据是否延迟(窗口合并,清理注册这块逻辑不讲了,那块还没深入去看):
Timestamp=1,Watermark=0,这里我们主要关注两个方法判断窗口和数据延时
isWindowLate = true && 3 <= -9223372036854775808L 返回 false
isElementLate = true && 1+0 <= -9223372036854775808L 返回 false ;
WindowOperator 类中:
TimeWindow 类中:
InternalTimerServiceImpl类中:
判断窗口是否触发计算:
数据(a,1,1) window(1,4), Timestamp=1,Watermark=0, currentWatermark = 0,
AbstractStreamOperator类中:
此时peek()拿出a window,3<=0 返回false,a窗口不触发
2. (b,1,1) 数据进来,window(1,4) Timestamp=1,Watermark=0
isWindowLate = true && 3 <=0 返回 false
isElementLate = true && 1+0 <= 0 返回 false ;
Watermark=0 和 第一条数据的watermark相同不会触发advancewatermark方法
3. (b,3,1) 数据进来, window(3,6) 会进行窗口合并为(1,6), timestamp=3,watermark=2
isWindowLate = true && 5 <=0 返回 false
isElementLate = true && 3+0 <= 0 返回 false ;
判断窗口是否触发计算:
window a(1,4) 3<=2 返回false,a窗口不触发
window b(1,6) 5<=2 返回false,b窗口不触发
4. (b,5,1) 数据进来, window(5,8) 会进行窗口合并为(1,8), timestamp=5,watermark=4
isWindowLate = true && 7 <=2 返回 false
isElementLate = true && 5+0 <=2 返回 false ;
判断窗口是否触发计算:
window a(1,4) 3<=4 返回true,a窗口触发
window b(1,8) 7<=4 返回false,b窗口不触发
调用WindowOperator .onEventTime
输出(a,1,1)
5. (a,1,2)数据进入, window(1,4) ,timestamp=1,watermark=0
isWindowLate = true && 3 <= 4 返回 true
isElementLate = true && 1+0 <=4 返回 true;
这条数据被丢弃。
后面的数据处理都是一样,套用就可以。