我有一个带有3个分区的Kafka主题,我正在使用Spark结构化流传输来使用这些数据。我有3个消费者(让我们说消费者A组)每个都从单个分区读取,直到这里一切都在工作文件中。
我有一个读取同一主题的新要求,我想通过再次创建3个使用者(例如,使用者组B)来使它并行化,每个使用者都从单个分区读取一次。在使用结构化流式传输时,我无法明确提及group.id
。
来自不同组的指向单个/相同分区的消费者会读取所有数据吗?
答案 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,这使两个作业都可以独立于另一个作业读取主题中的所有消息。