避免多个流式查询

Avoiding multiple streaming queries

我有一个结构化的流式查询,它下沉到 Kafka。此查询具有复杂的聚合逻辑。

我想将此查询的输出 DF 汇入多个 Kafka 主题,每个主题分区在不同的“键”列上。我不想为每个不同的 Kafka 主题设置多个 Kafka 接收器,因为这意味着 运行 多个流式查询 - 每个 Kafka 主题一个,特别是因为我的聚合逻辑很复杂。

问题:

  1. 有没有一种方法可以将结构化流式查询的结果输出到多个 Kafka 主题,每个主题都有不同的键列,而不必执行多个流式查询?

  2. 如果不是,那么级联多个查询是否有效,以便第一个查询进行复杂的聚合并将输出写入 Kafka,然后其他查询只读取第一个查询的输出,然后将他们的主题写入 Kafka,从而避免再次进行复杂的聚合?

在此先感谢您的帮助。

无法在开箱即用的结构化流中进行一次读取和多次写入。唯一的方法是实现将写入多个主题的自定义接收器。

每当您调用 dataset.writeStream().start() 时,spark 都会启动一个从源 (readStream()) 读取并写入接收器 (writeStream()) 的新流。

即使您尝试级联,它 spark 也会创建两个独立的流,每个流都有一个源和一个接收器。也就是说,它会读取、处理和写入数据两次:

Dataset df = <aggregation>; 
StreamingQuery sq1 = df.writeStream()...start(); 
StreamingQuery sq2 = df.writeStream()...start();

有一种方法可以在 Spark Streaming 中缓存读取数据,但此选项不适用于结构化流。

所以答案有点直勾勾地盯着我看。它也被记录在案。 Link 下面。

一个人可以从单个查询写入多个 Kafka 主题。如果您要写入的数据框有一个名为 "topic" 的列(以及 "key" 和 "value" 列),它会将一行的内容写入该行的主题。这会自动起作用。因此,您唯一需要弄清楚的是如何生成该列的值。

这是有记录的 - https://spark.apache.org/docs/latest/structured-streaming-kafka-integration.html#writing-data-to-kafka

我也在寻找这个问题的解决方案,就我而言,它不一定是 kafka sink。我想在 sink1 中写入一些数据帧的记录,而在 sink2 中写入一些其他记录(取决于某些条件,而不是在 2 个流式查询中读取相同的数据两次)。 目前,根据当前实现似乎不可能(DataSource.scala 中的 createSink() 方法提供对单个接收器的支持)。

但是,在 Spark 2.4.0 中,有一个新的 api 即将到来:foreachBatch() 将为数据帧微批提供句柄,可用于缓存数据帧、写入不同的接收器或处理多个在取消缓存 aagin 之前的时间。 像这样:

streamingDF.writeStream.foreachBatch { (batchDF: DataFrame, batchId: Long) =>
  batchDF.cache()
  batchDF.write.format(...).save(...)  // location 1
  batchDF.write.format(...).save(...)  // location 2
  batchDF.uncache()
}

现在此功能在数据块运行时可用: https://docs.databricks.com/spark/latest/structured-streaming/foreach.html#reuse-existing-batch-data-sources-with-foreachbatch

编辑 15/Nov/18: 现在可在 Spark 2.4.0 ( https://issues.apache.org/jira/browse/SPARK-24565)

中使用