Kafka消费群和带有Spark结构化流的分区

时间:2019-02-28 10:13:30

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

我有一个带有3个分区的Kafka主题,我正在使用Spark结构化流传输来使用这些数据。我有3个消费者(让我们说消费者A组)每个都从单个分区读取,直到这里一切都在工作文件中。

我有一个读取同一主题的新要求,我想通过再次创建3个使用者(例如,使用者组B)来使它并行化,每个使用者都从单个分区读取一次。在使用结构化流式传输时,我无法明确提及group.id

来自不同组的指向单个/相同分区的消费者会读取所有数据吗?

3 个答案:

答案 0 :(得分:1)

从Spark 3.0.1 documentation

默认情况下,每个查询都会生成用于读取数据的唯一组ID。 这样可以确保每个Kafka来源都有自己的消费群体, 不会受到任何其他消费者的干扰,因此可以 阅读其订阅主题的所有分区。

因此,如果您使用assign选项并提及要使用哪个分区,则会从特定分区读取所有数据,因为默认情况下,它将是一个不同的使用者组(group.id)。 assign选项将json字符串作为值,并且可以具有来自不同主题的多个分区。例如{"topicA":[0,1],"topicB":[2,4]}

val df = spark
  .read
  .format("kafka")
  .option("kafka.bootstrap.servers", "host:port")
  .option("assign", "{"topic-name":[0]}")
  .load()

答案 1 :(得分:0)

用户可以使用以下group.id进行流式传输

String processingGroup =“ processingGroupA”;

Dataset<Row> raw_df = sparkSession
                      .readStream()
                      .format("kafka")
                      .option("kafka.bootstrap.servers", consumerAppProperties.getProperty(BOOTSTRAP_SERVERS_CONFIG))
                      .option("subscribe", topicName) 
                      .option("startingOffsets", "latest")
                      .option("group.id",  processingGroup)
                      .load();

答案 2 :(得分:0)

除非您使用的是Spark 3.x或更高版本,否则您将无法在Kafka输入流中设置group.id。如前所述,使用Spark 3.x,您可以拥有两个不同的结构化流作业,提供两个不同的group.id,以确保每个作业独立于另一个作业读取主题的所有消息。

对于<= 2.4.x版本的Spark,Spark本身将为您创建一个唯一的消费者组,您可以在code on GitHub中进行查找:

// Each running query should use its own group id. Otherwise, the query may be only 
// assigned partial data since Kafka will assign partitions to multiple consumers having
// the same group id. Hence, we should generate a unique id for each query.
val uniqueGroupId = s"spark-kafka-source-${UUID.randomUUID}-${metadataPath.hashCode}"

因此,在那种情况下,具有两个不同的流作业也将确保您具有两个不同的ConsumerGroup,这使两个作业都可以独立于另一个作业读取主题中的所有消息。