Q) 如果 Kafka 主题有 3 个分区,那么 3 个 spark 执行器将并行运行,每个读取一个分区。
更具体地说,将有 3 个任务提交给 Spark 集群,每个分区一个。 在何处执行这些任务取决于您的集群拓扑和位置设置,但通常您可以认为这 3 个任务将并行运行。
Q) 假设我在读取数据后有一个窗口操作。窗口操作是跨分区还是在一个分区内应用窗口?
Spark 的基本模型和 Spark Streaming 的传递性是在抽象上声明操作(Spark 的 RDD/Datasets,Spark Streaming 的 DStream),并且在执行级别,这些操作将以分布式方式应用,使用数据的本机分区。
((我不确定问题在“跨分区还是在一个分区内”之间的区别。窗口将按分区保留。操作将根据它们自己的语义应用。例如,map 操作将应用于每个分区,而count 操作将首先应用于每个分区,然后合并为一个结果。))
关于伪代码:
val dstream = createDirectStream(..., Seconds(30))
dstream.window(Seconds(600)) // this does nothing as the new dstream is not referenced any further
val windowDstream = dstream.window(timePeriod) // this creates a new Windowed DStream based on the base DStream
dstream.saveAsTextFiles() // this writes using the original streaming interval (30 seconds). It will write 1 logical file in the distributed file system with 3 partitions
windowDstream.saveAsTextFiles() // this writes using the windowed interval (600 seconds). It will write 1 logical file in the distributed file system with 3 partitions.
鉴于此代码(注意命名更改!):
val dstream = createDirectStream(...)
dstream.action1()
val windowDStream = dstream.window(...)
windowDStream.action2()
对于 action2,是否会使用相同的执行器集(否则,必须再次从 Kafka 读取数据 - 不好)?
在 Direct Stream 模型的情况下,每个间隔的 RDD 不包含任何数据,仅包含偏移量(offset-start, offset-end)。仅在应用操作时才会读取数据。
因此,直接生产者上的窗口化 dstream 只是一系列偏移量:Window (1-3) = (offset1-start, offset1-end), (offset2-start, offset2-end), (offset3-start, offset3-end)。当对该窗口应用操作时,将从 Kafka 获取这些偏移量并应用该操作。正如问题所暗示的那样,这并不“坏”。这使我们不必长时间存储中间数据,并让我们保留数据上的操作语义。
所以,是的,数据将被再次读取,这是一件好事。