传入数据是流,如下所示,由3列组成
[
system -> deviceId,
time -> eventTime
value -> some metric
]
+-------+-------------------+-----+
|system |time |value|
+-------+-------------------+-----+
|system1|2019-08-20 07:13:10|1.5 |
|system2|2019-08-20 07:11:10|1.9 |
|system3|2019-08-20 07:13:15|1.3 |
|system1|2019-08-20 07:13:20|1.8 |
|system2|2019-08-20 07:11:20|1.6 |
|system3|2019-08-20 07:13:25|1.4 |
|system1|2019-08-20 07:13:30|1.2 |
|system2|2019-08-20 07:11:30|1.1 |
|system3|2019-08-20 07:13:35|1.5 |
+-------+-------------------+-----+
每个设备以固定间隔[10秒]产生数据,
我有一个Spark结构化的流应用程序,它可以使用
计算价值的最大值窗口持续时间= 30秒
滑动时间= 30秒
df.withWatermark("time", "30 seconds")
.groupBy(
window(col("time"), "30 seconds", "30 seconds"),
col("system")
)
.agg(max("value"))
问题 由于每个设备都是独立的,因此时钟也是独立的。由于各种原因,例如:[网络问题,设备的高使用率等]
,设备可能被阻塞并延迟了数据发送现在作为单个作业处理数据,它将开始基于水印删除阻塞设备的数据,而我们正在丢失数据。
有什么办法或解决方法,以便可以将水印与deviceId绑定在一起。因此该作业会按[deviceId EventTime]维护水印,并且不会因为其他设备而丢弃它。
答案 0 :(得分:0)
在https://towardsdatascience.com/watermarking-in-spark-structured-streaming-9e164f373e9中,我无法自己说得更好:
自Spark 2.1以来,水印已引入结构化流中 API。您只需将withWatermark-Operator添加到 查询:
withWatermark(eventTime:String,delayThreshold:String):
Dataset [T]它需要两个参数,a)事件时间列(必须为 与汇总工作相同)和b)指定阈值 应该处理多长时间的数据(以事件时间为单位)。的 然后,Spark将保持聚合的状态,直到达到最大值 eventTime — delayThreshold> T,其中最大eventTime是最新的 引擎看到的事件时间,T是窗口的开始时间。 如果最新数据落入此阈值内,则查询将更新 最终(下图中的右图)。否则会得到 删除并且不会触发任何重新处理(下图左图)。
如您所见,该概念不涉及添加元数据拆分,例如设备ID。