Spark-将kafka流式传输到每天都会更改的文件吗?

时间:2019-03-15 14:25:11

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

我有一个将在火花中处理的kafka流。我想将此流的输出写入文件。但是,我想按天对这些文件进行分区,因此每天它将开始写入新文件。可以这样做吗?我希望它保持运行状态,当发生新的一天时,它将切换为写入新文件。

val streamInputDf = spark.readStream.format("kafka")
                    .option("kafka.bootstrapservers", "XXXX")
                    .option("subscribe", "XXXX")
                    .load()
val streamSelectDf = streamInputDf.select(...)

streamSelectDf.writeStream.format("parquet)
     .option("path", "xxx")
     ???

2 个答案:

答案 0 :(得分:2)

  

可以通过提供的partitionBy从spark添加分区   DataFrameWriter(用于非流媒体)或DataStreamWriter(用于非流媒体)   流数据。


下面是签名:

  

公共DataFrameWriter partitionBy(scala.collection.Seq   colNames)

     

DataStreamWriter partitionBy(scala.collection.Seq colNames)   按文件系统上给定的列对输出进行分区。

     

DataStreamWriter partitionBy(String ... colNames)对   通过文件系统上给定的列输出。

     

说明:   partitionBy通过public DataStreamWriter partitionBy(String ... colNames)   按文件系统上给定的列对输出进行分区。如果   指定后,输出将放置在类似于Hive的文件系统上   分区方案。例如,当我们通过   一年又一个月,目录布局如下:

 
- year=2016/month=01/ 
- year=2016/month=02/
     

分区是最广泛用于优化的技术之一   物理数据布局。它提供了用于跳过的粗粒度索引   当查询对分区进行断言时,不必要的数据读取   列。为了使分区正常工作,   每列中的不同值通常应小于几十   数千。

     

参数:colNames-(未记录)返回:(未记录)由于:   2.0.0

因此,如果要按年份和月份对数据进行分区,spark会将数据保存到以下文件夹中:

year=2019/month=01/05
year=2019/month=02/05

选项1 (直接写入): 您已经提到过实木复合地板-您可以通过以下方式使用保存为实木复合地板格式:

df.write.partitionBy('year', 'month','day').format("parquet").save(path)

选项2 (使用相同的partitionBy插入到蜂巢中):

您还可以像下面这样插入配置单元表:

df.write.partitionBy('year', 'month', 'day').insertInto(String tableName)

获取所有配置单元分区:

Spark sql基于配置单元查询语言,因此您可以使用SHOW PARTITIONS

获取特定表中的分区列表。

sparkSession.sql("SHOW PARTITIONS partitionedHiveParquetTable")

结论: 我建议使用选项2 ...因为Advantage是稍后使用的,您可以基于分区查询数据(也可以查询原始数据以了解所收到的内容),并且基础文件可以是镶木地板或orc。

注意:

在创建与.enableHiveSupport()的会话时,请确保已拥有SparkSessionBuilder,并确保是否已正确配置hive-conf.xml等。

答案 1 :(得分:1)

基于this answer,spark应该能够根据年,月和日写入文件夹,这似乎正是您要查找的内容。尚未在Spark Streaming中尝试过它,但希望该示例能使您走上正确的轨道:

df.write.partitionBy("year", "month", "day").format("parquet").save(outPath)

如果没有,您可能可以基于current_date()

放入变量文件路径