Flink笔记-Evictors数据剔除
编程过程当中,可以通过调用DataStream API的evictor()方法【可选方法】传入相应的Evictor对进入WindowFunction前后的数据进行剔除处理,默认的Evictors都是在WindowFunction计算之前对数据进行剔除处理的。Flink本身实现了三种Evictor,其中有CountEvictor,DeltaEvictor和TimeEvictor。
Evictors Type
CountEvictor
- 定义:在窗口中保持固定数量的数据,将超过指定大小的数据在窗口计算之前剔除。
- demo:仅保留窗口中10条数据
.evictor(CountEvictor.of(10)).
- 内部剔除逻辑代码实现
从中看出,剔除逻辑仅为如果当前窗口内数据条数小于等于传入的用户指定最大保留条数则不做剔除处理;否则去除掉多余的数据,去除多余数据用到的一个技巧:
int evictedCount = 0;
evictedCount++;
if (evictedCount > size - maxCount) {
break;
} else {
iterator.remove();
}
此段代码通过定义一个自增变量来控制remove的数量,从而实现去除多余的数据,eg:size为12,maxCount为10,不难得出当evictedCount自增三次时,会走break逻辑,即会remove两次,从而达到目的。我们从中还可以看出元素在窗口中没有保持顺序,因此如果对数据在进入WindowFunction之前或者之后进行预处理,其实和数据进入窗口的顺序是没有关系的,我们无法控制绝对的先后关系。
- 默认情况下数据在窗口计算之前剔除可以从构造函数中看出:
TimeEvictor
- 概念:通过指定时间间隔,将当前窗口中最新元素的时间减去Interval,然后将小于该结果的数据全部剔除,其本质是将具有最新时间的数据选择出来,删除过时的数据。
- demo:仅保留最新10ms内数据
.evictor(TimeEvictor.of(Time.milliseconds(10)))
- 同样的,默认是在窗口计算之前剔除
- 内部剔除核心逻辑代码实现
获取当前窗口数据中最大的时间戳,减去 用户指定的转换为ms的时间间隔,得到一个evictCutoff,然后迭代元素,过滤掉时间戳小于等于evictCutoff的元素。
比如:当前窗口元素中最大时间戳为1566651251663,用户 指定TimeEvictor.of(Time.milliseconds(10),即evictCutoff就为1566651251663-10=1566651251653,即时间戳小于1566651251653的元素均为被剔除。
DeltaEvictor
- 描述:通过定义DeltaFunction和指定threshold,并计算Windows中的元素与最新元素之间的Delt大小,如果超过了threshold则将当前数据元素剔除。
- demo:剔除值差大于1的元素。
timeWindow(Time.seconds(10)).evictor(DeltaEvictor.of(1, new DeltaFunction<Tuple2<String, Long>>() {
@Override
public double getDelta(Tuple2<String, Long> oldDataPoint, Tuple2<String, Long> newDataPoint) {
return oldDataPoint.f1-newDataPoint.f1;
}
})).
- 内部剔除核心逻辑代码实现
关键点在这里:
deltaFunction.getDelta(element.getValue(), lastElement.getValue()) >= this.threshold
获取最新的元素,遍历窗口元素集合,调用用户定义好的deltaFunction求取结果与threshold作比较,满足条件的剔除掉。
自定义Evictor
可以通过实现Evictor接口且覆写evictBefore和evictAfter方法完成自定义Evictor,从而满足自身的业务场景。