我有一个用例,其中我使用星火结构流从卡夫卡消费数据。我要订阅多个主题,并且根据 topic 名称,数据框应转储到定义的位置(不同主题的不同位置)。我看到是否可以在spark数据帧中使用某种拆分/过滤器功能解决此问题,但找不到任何解决方案。
到目前为止,我仅订阅了一个主题,并且使用自己的书面方法将数据转储为拼花形式的位置。这是我当前正在使用的代码:
def save_as_parquet(cast_dataframe: DataFrame,output_path:
String,checkpointLocation: String): Unit = {
val query = cast_dataframe.writeStream
.format("parquet")
.option("failOnDataLoss",true)
.option("path",output_path)
.option("checkpointLocation",checkpointLocation)
.start()
.awaitTermination()
}
当我订阅不同的主题时,此cast_dataframe也将具有来自不同主题的值。我希望将数据从主题仅转储到为其分配位置的位置。该怎么办?
答案 0 :(得分:1)
如将要编写的official documentation Dataset
中所述,可能包含可选的topic
列,该列可用于消息路由:
*如果未指定“ topic”配置选项,则必须填写topic列。
值列是唯一必需的选项。如果未指定键列,则将自动添加空值键列(请参阅有关如何处理空值键值的Kafka语义)。如果存在主题列,则在将给定行写入Kafka时将其值用作主题,除非设置了“ topic”配置选项,即“ topic”配置选项会覆盖主题列。
答案 1 :(得分:0)
根据文档,来自 Kafka 源的每一行具有以下架构:
列 | 类型 |
---|---|
键 | 二进制 |
价值 | 二进制 |
话题 | 字符串 |
... | ... |
假设您正在使用 source 选项阅读多个主题
val kafkaInputDf = spark.readStream.format("kafka").[...]
.option("subscribe", "topic1, topic2, topic3")
.start()
.selectExpr("CAST(key AS STRING)", "CAST(value AS STRING)", "topic")
然后您可以对列 topic
应用过滤器以相应地拆分数据:
val df1 = kafkaInputDf.filter(col("topic") === "topic1")
val df2 = kafkaInputDf.filter(col("topic") === "topic2")
val df3 = kafkaInputDf.filter(col("topic") === "topic3")
然后您可以将这三个流式数据帧 df1
、df2
和 df3
沉入它们所需的接收器中。由于这将创建三个并行运行的流查询,因此每个 writeStream
获得自己的检查点位置非常重要。