【问题标题】:Window operation on Spark streaming from Kafka来自 Kafka 的 Spark 流的窗口操作
【发布时间】:2017-11-23 19:29:39
【问题描述】:

我正在尝试探索来自 Kafka 的 Spark 流作为源。根据这个link,createDirectStream 在 kafka 分区和 Spark 之间具有 1:1 的并行性。所以这意味着,如果有一个 Kafka 主题有 3 个分区,那么 3 个 spark 执行器将并行运行,每个读取一个分区。

问题

  1. 假设我在读取数据后有一个窗口操作。窗口操作是跨分区还是在一个分区内应用窗口 分区,即假设我的批处理间隔是 10 秒和窗口间隔 是 50 多岁。窗口是否会跨分区累积 50s 数据的数据 (如果每个分区有 10 条记录,每条记录 50 秒,窗口是否保持 30 记录)或每个分区并行 50 个数据(如果每个分区 每个50s有10条记录,window是否有10条记录)?

    伪代码:

    rdd = createDirectStream(...)

    rdd.window()

    rdd.saveAsTextFile() //这个是写30条记录在1个文件还是3个文件 每个文件有 10 条记录?


  1. 假设我有这个......

    伪代码:

    rdd = createDirectStream()

    rdd.action1()

    rdd.window()

    rdd.action2()

    可以说,我有 3 个 kafka 分区和 3 个执行程序(每个读取一个 话题)。由于有 2 个动作,这会产生 2 个作业。每个火花执行器 将对 RDD 进行分区,并且并行应用 action1。 现在对于 action2,是否会使用相同的执行器集(否则, 必须再次从 Kafka 读取数据 - 不好)?

【问题讨论】:

    标签: window apache-kafka spark-streaming


    【解决方案1】:

    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 获取这些偏移量并应用该操作。正如问题所暗示的那样,这并不“坏”。这使我们不必长时间存储中间数据,并让我们保留数据上的操作语义。

    所以,是的,数据将被再次读取,这是一件好事。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-28
      • 1970-01-01
      • 2019-07-29
      • 2016-11-03
      • 1970-01-01
      • 2021-11-23
      • 1970-01-01
      • 2019-06-30
      相关资源
      最近更新 更多