我正在Spark结构化流2.2.1中使用dropDuplicates()方法,并且需要使用withWatermark()的有效解决方案,以减少状态。
我第一次尝试做到这一点是不正确的,因为我没有使用withWatermark()中定义的timestamp列来删除重复项,因为我实际上只想基于uuid列删除重复项在唯一的时间戳上。
然后我找到了答案https://stackoverflow.com/a/45543643,并认为我的问题已解决。但是我似乎以某种方式错误地实施了该计划,因为该州似乎仍会无限期增长并且永远不会被清理。
我遇到的情况是,在调用dropDuplicates()之后需要一个数据集,因此我向原始数据集添加了一个15分钟窗口的列,然后在该窗口上应用了watermark()并将“ window”列添加到了dropDuplicates( )。由于我需要的数据与应用dropDuplicates()之前的数据相同,因此我删除了“窗口”列,并使用相应的Encoder来获得所需的数据集。
这是我的代码:
Dataset<Context> contextDataset = ...;
contextDataset
.withColumn("window", functions.window(contextDataset.col("timestamp"), "15 minutes"))
.withWatermark("window", "15 minutes")
.dropDuplicates("uuid", "window")
.drop("window")
.as(Context.encoder());
我的设置是:从Kafka主题最多读取350000条消息,触发时间为5分钟。当我使用时:
contextDataset
.withWatermark("timestamp", "15 minutes")
.dropDuplicates("uuid", "timestamp")
微批次最多需要2.5分钟。
将上述解决方案与“窗口”一起使用时,流会在一段时间后降级,并且微批处理需要2个小时才能完成许多失败的任务,而且情况越来越糟。