Apache spark 为什么Spark Structured Streaming不允许更改输入源的数量?

Apache spark 为什么Spark Structured Streaming不允许更改输入源的数量?,apache-spark,pyspark,apache-kafka,spark-structured-streaming,Apache Spark,Pyspark,Apache Kafka,Spark Structured Streaming,我想建立一个Spark流媒体管道,读取多个卡夫卡主题(随着时间的推移,这些主题的数量会有所不同)。我打算停止流式处理作业,添加/删除新主题,并在需要更新流式处理作业中的主题时,使用中概述的两个选项之一再次启动作业: 在进一步调查后,我注意到以下几点,并试图理解为什么“不允许”更改输入源的数量: 输入源的数量或类型(即不同的源)发生变化:这是不允许的 “不允许”的定义(也来自): 术语“不允许”表示不应执行指定的更改,因为重新启动的查询可能会失败,并出现不可预测的错误。sdf表示使用sparkSe

我想建立一个Spark流媒体管道,读取多个卡夫卡主题(随着时间的推移,这些主题的数量会有所不同)。我打算停止流式处理作业,添加/删除新主题,并在需要更新流式处理作业中的主题时,使用中概述的两个选项之一再次启动作业:

在进一步调查后,我注意到以下几点,并试图理解为什么“不允许”更改输入源的数量:

输入源的数量或类型(即不同的源)发生变化:这是不允许的

“不允许”的定义(也来自):

术语“不允许”表示不应执行指定的更改,因为重新启动的查询可能会失败,并出现不可预测的错误。sdf表示使用sparkSession.readStream生成的流数据帧/数据集

我的理解是Spark结构化流媒体实现了自己的功能:

如果出现故障或故意关闭,可以恢复以前查询的进度和状态,并在停止时继续。这是使用检查点和预写日志完成的。您可以使用检查点位置配置查询,该查询将所有进度信息(即每个触发器中处理的偏移量范围)和正在运行的聚合(例如,快速示例中的字数)保存到检查点位置。此检查点位置必须是HDFS兼容文件系统中的路径,并且可以在启动查询时在DataStreamWriter中设置为选项


有人能解释为什么“不允许”更改源的数量吗?我认为这将是检查点机制的好处之一。

在现有运行模型流作业中添加新输入源的步骤

  • 停止运行模型的当前正在运行的流
  • hdfs dfs-获取输出/检查点/偏移量/偏移量
  • 目录中将有3个文件(因为最后3个偏移量由spark保存)。下面是单个文件的示例格式

    v1

    • 每个{“logOffset”:batchId}表示单个输入源
    • 要添加新的输入源,请在目录中每个文件的末尾添加“-”
    样本更新文件 v1

    • 若要添加多个输入源,请添加“-”等于新输入源的数量
    • hdfs dfs-put-f/偏移量输出/检查点/偏移量

      • 做你想做的事情的最好方法是在多线程中运行你的readStreams。 我在做这个,同时阅读40张表格。为此,我遵循这篇文章:

        我将在阅读并挂载我的代码结构、主函数、执行器以及spark会话的一个特性后,简要介绍一下我所做的工作,这些特性将与所有作业共享

        1.我想读的两个主题列表

        因此,在Scala中,我创建了两个列表。第一个列表是我一直想读的主题,第二个列表是一个动态列表,当我停止工作时,我可以在其中添加一些新主题

      • 运行作业的模式匹配
      • 我有两个不同的作业,一个是我运行到始终运行的表中的作业,另一个是我运行到特定主题的动态作业,换句话说,如果我想添加一个新主题并为他创建一个新作业,我会在模式匹配中添加此作业。在下面的代码中,我想对Cars和Ship表运行specfic作业,而我放在specific列表中的所有其他表都将运行相同的复制表作业

          var tables = specifcTables ++ dynamicTables
        
          tables.map(table => {
            table._1 match {
              case "CARS" => new CarsJob
              case "SHIPS" => new ShipsReplicationJob
              case _ => new ReplicationJob
        
        在此之后,我将此模式匹配传递给createjobs函数,该函数将实例化这些作业中的每一个,并将此函数传递给startFutureTask函数,后者将把这些作业中的每一个放在不同的线程中

        startFutureTasks(createJobs(tables))
        
        我希望我帮了忙。谢谢

        {"batchWatermarkMs":0,"batchTimestampMs":1578463128395,"conf":{"spark.sql.streaming.stateStore.providerClass":"org.apache.spark.sql.execution.streaming.state.HDFSBackedStateStoreProvider","spark.sql.streaming.flatMapGroupsWithState.stateFormatVersion":"2","spark.sql.streaming.multipleWatermarkPolicy":"min","spark.sql.streaming.aggregation.stateFormatVersion":"2","spark.sql.shuffle.partitions":"200"}}
        {"logOffset":0}
        {"logOffset":0}
        
          var tables = specifcTables ++ dynamicTables
        
          tables.map(table => {
            table._1 match {
              case "CARS" => new CarsJob
              case "SHIPS" => new ShipsReplicationJob
              case _ => new ReplicationJob
        
        startFutureTasks(createJobs(tables))