我有一个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")
其中一个比另一个“更有效率”吗?我找不到任何有关的文件。
谢谢!
答案 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个执行程序)。 在第二种情况下,将需要更多的内存和内核以用于额外的驱动程序。