我正在使用Spark Streaming从Kafka读取数据,并传递给py文件进行预测。它返回预测以及原始数据。它会将原始数据及其预测信息保存到文件中,但是会为每个RDD创建一个文件。 我需要一个包含所有收集到的数据的文件,直到停止程序保存到一个文件为止。
我尝试过writeStream,它甚至不创建单个文件。 我尝试使用append将其保存到拼花地板,但它会为每个RDD创建多个文件,该文件为1。 我试图用追加模式编写仍然有多个文件作为输出。 下面的代码创建一个文件夹output.csv并将所有文件输入其中。
def main(args: Array[String]): Unit = {
val ss = SparkSession.builder()
.appName("consumer")
.master("local[*]")
.getOrCreate()
val scc = new StreamingContext(ss.sparkContext, Seconds(2))
val kafkaParams = Map[String, Object](
"bootstrap.servers" -> "localhost:9092",
"key.deserializer"->
"org.apache.kafka.common.serialization.StringDeserializer",
"value.deserializer">
"org.apache.kafka.common.serialization.StringDeserializer",
"group.id"-> "group5" // clients can take
)
mappedData.foreachRDD(
x =>
x.map(y =>
ss.sparkContext.makeRDD(List(y)).pipe(pyPath).toDF().repartition(1)
.write.format("csv").mode("append").option("truncate","false")
.save("output.csv")
)
)
scc.start()
scc.awaitTermination()
在流式传输期间,我只需要一个文件,所有语句一一收集。
任何帮助将不胜感激,谢谢您的期待。
答案 0 :(得分:2)
一旦写入,您将无法修改hdfs中的任何文件。如果您希望实时写入文件(每2秒将来自流作业的数据块追加到同一文件中),则由于hdfs文件是不可变的,因此根本不允许这样做。我建议您尝试编写一个从多个文件读取的读取逻辑(如果可能)。
但是,如果必须从一个文件中读取文件,则建议在将输出写入单个csv / parquet文件夹后使用“ Append” SaveMode(这将为每个块创建零件文件)中的两种方法之一您每2秒写一次)。
您可以在spark中编写一个简单的逻辑来读取包含多个文件的该文件夹,然后使用reparation(1)或coalesce(1)将其作为单个文件写入另一个hdfs位置,然后从该位置读取数据。见下文:
spark.read.csv("oldLocation").coalesce(1).write.csv("newLocation")
答案 1 :(得分:1)
repartition-建议在不增加任何分区的情况下使用repartition,因为它涉及对所有数据的改组。
coalesce-建议在减少分区数量的同时使用合并。例如,如果您有3个分区,并且想要将其减少到2个分区,则Coalesce会将第3个分区数据移至分区1和2。分区1和2将保留在同一Container中。但是重新分区将在所有分区中重新排列数据,因此网络使用率执行器之间的间隔会很高,并且会影响性能。
明智的结合性能优于分区,同时减少了分区数量。
因此,在编写use选项时会结合在一起。 例如:df.write.coalesce