那么窗口会在什么时刻关闭呢?关闭窗口意味着完成计算并清空状态,严格意义上讲需要等窗口内数据都抵达后才能关闭窗口,但这个问题同样与应用场景相关。前面假定我们接收到一个窗口内读数的时刻是在9:00,说明延迟约1小时,那么在9:05时刻我们可能认为所有在8:00~8:05分的数据都已经被接收了,于是可以计算平均温度并关闭该窗口;或者,我们出于保守的目的,认为需要等到9:10才能确认数据完全接收。注意,无论我们最终选择9:05还是9:10,这都只是我们根据经验人为设定的一个估计值,并不能确保在此之前所有窗口内的数据都已经到达。当然,如果某个实时系统能够给出延迟的上界,我们就可以按照上界给出一个绝对可靠的时间。所以,流计算引擎并不能保证计算结果与事实一致,因为确保所有数据在给定时间之前抵达并非计算引擎需要考虑的问题,计算引擎要做的是提供完备的描述语义。
为了描述这种关闭窗口的时间,流计算引擎引入了一个称为水位线(Watermark)的概念。水位线实际上是一个映射关系,即根据当前系统的状态估计数据抵达情况。在前面的例子里,如果我们根据当前时间是9:10判断在8:05之前所有数据都已经抵达,则映射的输入是“当前时间9:10”,输出是“8:05”。当然也可以用其它状态来推测水位线,比如如果我们接收到8:05时刻的温度读数,则认为8:05之前所有数据已经抵达。并不存在完美普适的估计水位线的方法,而需要根据应用场景设定最适合的估计方法。
水位线一旦超过某个时间窗口的最大时间,则可以计算出窗口结果并关闭窗口。窗口关闭后,引擎就可以释放该窗口所占用的存储空间。在前面的例子里,计算平均值只需要保存两个值,但在有些场景下窗口内可能需要保存原始数据,那样的话对存储的占用开销会比较大。所以,准确地估计水位线非常重要。通常情况下,窗口保存的时间越短则存储代价越小、计算结果越粗糙;反之,则存储代价越大、计算结果越精确。计算引擎需要开发者来平衡开销和精度。
在一些流计算引擎里,除了水位线外还会有最大延迟的概念,即在水位线已经超过窗口最大时间后还需要维持一段时间。在某些场景下可能会使窗口定义更加灵活,但从窗口的生命期角度来说,最大延迟也只是水位线的一部分。