我希望将所有来自Kafka主题的汇总数据一次写入到一个Parquet文件中(或至少最后以一个Parquet文件结束)。
我运行一个单独的生产者应用程序,该应用程序将50条消息放在该主题上。 数据是在消费者应用中按时间(1天)汇总的,因此我需要收集1天以来的所有数据并进行计数。这项工作是这样完成的:
Dataset<Row> df = spark.readStream()
.format("kafka")
.option("kafka.bootstrap.servers", BOOTSTRAP_SERVER)
.option("subscribe", "test")
.option("startingOffsets", "latest")
.option("group.id", "test")
.option("failOnDataLoss", false)
.option("key.deserializer", "org.apache.kafka.common.serialization.IntegerDeserializer")
.option("value.deserializer", "org.apache.kafka.common.serialization.StringSerializer")
.load()
// LEFT OUT CODE FOR READABILITY
.withWatermark("timestamp", "1 minutes")
.groupBy(
functions.window(new Column("timestamp"), "1 day", "1 day"),
new Column("container_nummer"))
.count();
然后将结果写入像这样的镶木地板文件中:
StreamingQuery query = df.writeStream()
.format("parquet")
.option("truncate", "false")
.option("checkpointLocation", "/tmp/kafka-logs")
.start("/Users/**/kafka-path");
query.awaitTermination();
如果我将此写入控制台,最终我将获得批次1中每一天的正确计数。当尝试将其写入木地板时,我只会得到多个空的木地板文件。我这样阅读:
SparkSession spark = SparkSession
.builder()
.appName("test")
.config("spark.master", "local")
.config("spark.sql.session.timeZone", "UTC")
.getOrCreate();
Dataset<Row> df = spark.read()
.parquet("/Users/**/kafka-path/part-00000-dd416263-8db1-4166-b243-caba470adac7-c000.snappy.parquet");
df.explain();
df.show(20);
所有实木复合地板文件似乎都是空的(与将它们写入控制台相反),上面的代码输出如下:
+------+----------------+-----+
|window|container_nummer|count|
+------+----------------+-----+
+------+----------------+-----+
我有两个问题:
注意:它不需要在生产中运行。我只是希望有人知道一种解决方法。
谢谢!
答案 0 :(得分:0)
读取正在进行的流涉及的组件是结构化流。因此,您基本上正在读取无限制的消息/记录流,这些消息/记录将在数据到达时和写入时进行写入。以此为基础,Spark将继续分配执行者来执行读/写操作,并且将在此过程中创建多个文件。因此,您将不会拥有一个包含所有数据的文件。以下是可用于写入镶木地板文件的语法:
df..writeStream.queryName("Loantxns_view").outputMode("append").format("parquet").option("path", "/user/root/Ln_sink2").option("checkpointLocation", "/user/root/Checkpoints2").start()
尝试使用以下机制读取镶木地板文件,看看是否获得了所需的数据(ParquetDF是通过读取镶木地板目录路径读取的新数据框):
val ParquetDF = spark.read.parquet("/user/root/Ln_sink2")
ParquetDF.createOrReplaceTempView("xxxx_view");
spark.sql("select * from xxxx_view").show(false);
尝试一下,看看数据是否可见。