我们有一个Spark Streaming应用程序。 架构如下
将Kinesis激发到Kafka。
Spark应用程序正在使用qubole / kinesis-sql从Kinesis进行结构化流传输。然后汇总数据,然后将其推送到Kafka。
我们的用例需要延迟4分钟才能推送到Kafka。
加窗2分钟,水印4分钟
val windowedCountsDF = messageDS
.withWatermark("timestamp", "4 minutes")
.groupBy(window($"timestamp", "2 minutes", "2 minutes"), $"id", $"eventType", $"topic")
每两分钟触发一次写入Kafka的操作
val eventFilteredQuery = windowedCountsDF
.selectExpr("topic", "id as key", "to_json(struct(*)) AS value")
.writeStream
.trigger(Trigger.ProcessingTime("2 minutes"))
.format("org.apache.spark.sql.kafka010.KafkaSourceProvider")
.option("checkpointLocation", checkPoint)
.outputMode("update")
.option("kafka.bootstrap.servers", kafkaBootstrapServers)
.queryName("events_kafka_stream")
.start()
我可以更改触发时间以匹配窗口,但是仍然有些事件会立即推送到kafka。
有什么方法可以在窗口完成后的几分钟内延迟对Kafka的写入。
谢谢
答案 0 :(得分:1)
将输出模式从update
更改为append
(默认选项)。 output
模式会将所有更新的行写入接收器,因此,是否使用水印将无关紧要。
但是,在append
模式下,任何写入都需要等待,直到越过水印为止-这正是您想要的:
附加模式使用水印删除旧的聚合状态。但是窗口式聚合的输出会延迟
withWatermark()
中指定的延迟阈值,这是由于模式语义所致,行完成后(即,越过水印之后)只能将行添加到结果表一次。