我想编写一个结构化的Spark流式Kafka使用者,该使用者从一个分区Kafka主题中读取数据,按“键”将传入的数据重新划分为3个Spark分区,同时保持每个键对消息的排序,然后将其写入另一个Kafka主题有3个分区。
我使用了Dataframe.repartition(3, $"key")
,我相信它使用的是HashPartitioner。代码在下面提供。
当我以固定间隔间隔触发类型执行查询时,我直观地验证了输出消息的顺序是否正确。我的假设是不能保证结果分区上的顺序。我希望在Spark代码仓库或文档中的代码指针方面得到肯定或否决。
我也尝试使用Dataframe.sortWithinPartitions
,但是在没有聚合的流数据帧上似乎不支持此功能。
我尝试的一个选项是将数据帧转换为RDD并应用repartitionAndSortWithinPartitions
,该case class KVOutput(key: String, ts: Long, value: String, spark_partition: Int)
val df = spark.readStream.format("kafka")
.option("kafka.bootstrap.servers", kafkaBrokers.get)
.option("subscribe", Array(kafkaInputTopic.get).mkString(","))
.option("maxOffsetsPerTrigger",30)
.load()
val inputDf = df.selectExpr("CAST(key AS STRING)","CAST(value AS STRING)")
val resDf = inputDf.repartition(3, $"key")
.select(from_json($"value", schema).as("kv"))
.selectExpr("kv.key", "kv.ts", "kv.value")
.withColumn("spark_partition", spark_partition_id())
.select($"key", $"ts", $"value", $"spark_partition").as[KVOutput]
.sortWithinPartitions($"ts", $"value")
.select($"key".cast(StringType).as("key"), to_json(struct($"*")).cast(StringType).as("value"))
val query = resDf.writeStream
.format("kafka")
.option("kafka.bootstrap.servers", kafkaBrokers.get)
.option("topic", kafkaOutputTopic.get)
.option("checkpointLocation", checkpointLocation.get)
.start()
根据给定的分区程序对RDD进行重新分区,并在每个结果分区中,按其键对记录进行排序。但是,然后我无法在query.writestream操作中使用此RDD将结果写入输出Kafka主题中。
传入数据:
8/11/08 22:13:20 ERROR ApplicationMaster: User class threw exception: org.apache.spark.sql.AnalysisException: Sorting is not supported on streaming DataFrames/Datasets, unless it is on aggregated DataFrame/Dataset in Complete output mode;;
我提交此申请时,失败并显示
Get-AzureRmDatalakeStoreItemAclEntry -Account "XYZDLAKE01" -Path "\"
Scope Type Id Permission
----- ---- -- ----------
Access User 0******9-2**f-4**0-7**e-d**********2 r-x
Access Group rwx
Access Group b******3-2**a-3**4-2**a-e**********4 rwx
Default User rwx
Default User 7******d-2**c-e**0-5**3-4**********1 r-x
Default Group rwx
Default Group 3******3-2**6-1**9-a**3-5**********e rwx
Default Mask rwx
Default Other ---
Access User rwx
Access Other ---
Access Mask rwx