Apache kafka 如何在不覆盖的情况下将Spark流式输出写入HDFS

Apache kafka 如何在不覆盖的情况下将Spark流式输出写入HDFS,apache-kafka,spark-streaming,Apache Kafka,Spark Streaming,经过一些处理后,我得到了一个DStream[String,ArrayList[String]],因此,当我使用saveAsTextFile将其写入hdfs时,每次批处理后,它都会覆盖数据,因此如何通过附加到以前的结果来写入新结果呢 output.foreachRDD(r => { r.saveAsTextFile(path) }) 编辑::如果有人能帮助我将输出转换为avro格式,然后通过追加写入HDFS,则不支持追加。如果使用固定文件名调用,则每次都会覆盖它。 我们可以做saveA

经过一些处理后,我得到了一个DStream[String,ArrayList[String]],因此,当我使用saveAsTextFile将其写入hdfs时,每次批处理后,它都会覆盖数据,因此如何通过附加到以前的结果来写入新结果呢

output.foreachRDD(r => {
  r.saveAsTextFile(path)
})

编辑::如果有人能帮助我将输出转换为avro格式,然后通过追加写入HDFS,则不支持追加。如果使用固定文件名调用,则每次都会覆盖它。 我们可以做
saveAsTextFile(路径+时间戳)
每次都保存到一个新文件。这是
DStream.saveAsTextFiles(path)

一种支持
append
的易于访问的格式是拼花地板。我们首先将数据RDD转换为
DataFrame
Dataset
,然后我们可以从该抽象之上提供的写支持中获益

case class DataStructure(field1,..., fieldn)

... streaming setup, dstream declaration, ...

val structuredOutput = outputDStream.map(record => mapFunctionRecordToDataStructure)
structuredOutput.foreachRDD(rdd => 
  import sparkSession.implicits._
  val df = rdd.toDF()
  df.write.format("parquet").mode("append").save(s"$workDir/$targetFile")

})

请注意,随着时间的推移,附加到拼花文件的成本会越来越高,因此不时旋转目标文件仍然是一项要求。

如果要附加相同的文件并将其存储在文件系统中,请将其存储为拼花文件。你可以自己做

  kafkaData.foreachRDD( rdd => {
  if(rdd.count()>0)
  {
    val df=rdd.toDF()
    df.write(SaveMode.Append).save("/path")
   }

将流输出存储到HDFS将始终创建一个新文件,即使是在使用“附加到拼花地板”时,也会导致Namenode上出现小文件问题。我建议您将输出写入序列文件,这样您就可以继续附加到同一个文件。

在这里,我解决了没有数据帧的问题

import java.time.format.DateTimeFormatter
import java.time.LocalDateTime

 messages.foreachRDD{ rdd =>
    rdd.repartition(1)
    val eachRdd = rdd.map(record => record.value)
    if(!eachRdd.isEmpty) {
      eachRdd.saveAsTextFile(hdfs_storage + DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now) + "/")
    }
  }

任何将RDD[String,ArrayList]字符串转换为avro格式的代码,我都有一个模式。上面的追加代码只是为每个批创建新文件,而不是追加到同一个文件。它追加到同一个逻辑文件,但实际上是在文件系统中创建小的
部分xxxx
文件。您可以使用
sparkSession.read.parquet(path)
一次加载所有数据。从Spark Streaming,我建议将数据写入分布式数据库,如Cassandra,而不是fs。请帮助我解决此错误。是否有方法可以将每个Spark Streaming批处理的数据保存到一个seprate文件中。我需要行“/rootpath/batch\u id/filename”中的内容?另请参阅:然后它还会创建多个文件@伊珊·库玛迪:你测试过这个吗?我认为它会将新文件添加到/path目录中