从多个Kafka主题中读取Spark结构化的流式应用程序

时间:2019-04-30 22:41:32

标签: apache-spark apache-kafka spark-structured-streaming

我有一个Spark结构化的流应用程序(v2.3.2),该应用程序需要读取多个Kafka主题,进行一些相对简单的处理(主要是聚合和一些联接),并将结果发布到其他多个Kafka主题中。因此,在同一个应用中可以处理多个流。

我想知道它是否从资源(内存,执行程序,线程,Kafka侦听器等)的角度来看是否有所不同,如果我只设置1个直接readStream来订阅多个主题,然后用selects拆分流,相比每个主题1个readStream。

类似

df = spark.readStream.format("kafka").option("subscribe", "t1,t2,t3")
...
t1df = df.select(...).where("topic = 't1'")...
t2df = df.select(...).where("topic = 't2'")...

vs。

t1df = spark.readStream.format("kafka").option("subscribe", "t1")
t2df = spark.readStream.format("kafka").option("subscribe", "t2")

其中一个比另一个“更有效率”吗?我找不到任何有关的文件。

谢谢!

2 个答案:

答案 0 :(得分:1)

每个动作都需要完整的血统执行。您最好将其分为三个独立的kafka读取。否则,您将读取每个主题N次,其中N是写入次数。

我真的建议不要这样做,但是如果您想将所有主题都放在同一阅读中,请执行以下操作:

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

答案 1 :(得分:0)

从资源(内存和内核)的角度来看,如果在群集上将其作为多个流(多个驱动器-执行器)运行,则会有所不同。

在第一种情况下,您提到-

df = spark.readStream.format("kafka").option("subscribe", "t1,t2,t3")... t1df = df.select(...).where("topic = 't1'")... t2df = df.select(...).where("topic = 't2'")...

考虑到上面将提供一个驱动程序和2个执行程序。

在第二种情况下-

t1df = spark.readStream.format("kafka").option("subscribe", "t1") t2df = spark.readStream.format("kafka").option("subscribe", "t2")

您可以将它们作为不同的流运行-2个驱动程序和2个执行程序(每个1个执行程序)。 在第二种情况下,将需要更多的内存和内核以用于额外的驱​​动程序。