Apache spark 如何将spark sql查询的所有输出保存到文本文件中

Apache spark 如何将spark sql查询的所有输出保存到文本文件中,apache-spark,save,apache-spark-sql,spark-streaming,Apache Spark,Save,Apache Spark Sql,Spark Streaming,我正在使用spark streaming编写一个简单的消费者程序。我的代码将部分数据保存到文件中,但不是所有数据。谁能帮我解决这个问题吗。我不确定我在哪里丢失了数据。我从kafka主题中获取数据,然后应用JavaBean类中的模式 public class ConsumerFile { public static void main(String[] args){ Logger.getLogger("org").setLevel(Level.OFF); Logger.getLogger("akk

我正在使用spark streaming编写一个简单的消费者程序。我的代码将部分数据保存到文件中,但不是所有数据。谁能帮我解决这个问题吗。我不确定我在哪里丢失了数据。我从kafka主题中获取数据,然后应用JavaBean类中的模式

public class ConsumerFile {
public static void main(String[] args){
Logger.getLogger("org").setLevel(Level.OFF);
Logger.getLogger("akka").setLevel(Level.OFF);
String topic = args[0];
final String path=new String(args[2]);
String broker = args[1];
SparkConf sparkConf = new SparkConf().setAppName("SparkConsumer").setMaster("local[*]");;
    JavaStreamingContext ssc = new JavaStreamingContext(sparkConf, Durations.seconds(2));
    HashSet<String> topicsSet = new HashSet<String>(Arrays.asList(topic.split(",")));

    HashMap<String, String> kafkaParams = new HashMap<String, String>();

    kafkaParams.put("metadata.broker.list", broker);
    JavaPairInputDStream<String, String> kafkaStream = KafkaUtils.createDirectStream(
    ssc, String.class, String.class,StringDecoder.class,StringDecoder.class,kafkaPrams,
topicsSet
);

JavaDStream<String> words = kafkaStream.map(new Function<Tuple2<String, String>, String>() 

                                         {
                   public String call(Tuple2<String, String> message)

                                             {
                                                 return message._2();}});
words.foreachRDD(
          new Function2<JavaRDD<String>, Time, Void>() {
       public Void call(JavaRDD<String> rdd, Time time) {
   SQLContext sqlContext = JavaSQLContextSingleton.getInstance(rdd.context());
              // Convert RDD[String] to RDD[case class] to DataFrame
              JavaRDD<JavaRow> rowRDD = rdd.map(new Function<String, JavaRow>() {
                public JavaRow call(String line) throws Exception{
                String[] fields = line.split(",");
                  JavaRow record = new JavaRow(fields[0], fields[1],fields[2]  );

                  return record;

                }

              });

              DataFrame wordsDataFrame = sqlContext.createDataFrame(rowRDD, JavaRow.class);
              wordsDataFrame.registerTempTable("Data");
              DataFrame wDataFrame = sqlContext.sql(" select * from Data");  
              if(!wDataFrame.rdd().isEmpty()){
             wDataFrame.rdd().coalesce(1,true,null).saveAsTextFile(path); }
              return null;
            }} );
ssc.start();
 ssc.awaitTermination();}
公共类用户文件{
公共静态void main(字符串[]args){
Logger.getLogger(“org”).setLevel(Level.OFF);
Logger.getLogger(“akka”).setLevel(Level.OFF);
字符串主题=args[0];
最终字符串路径=新字符串(args[2]);
字符串代理=args[1];
SparkConf SparkConf=new SparkConf().setAppName(“SparkConsumer”).setMaster(“local[*]”);;
JavaStreamingContext ssc=新的JavaStreamingContext(sparkConf,Durations.seconds(2));
HashSet-topicsSet=新的HashSet(Arrays.asList(topic.split(“,”));
HashMap kafkaParams=新HashMap();
kafkaParams.put(“metadata.broker.list”,broker);
JavaPairInputStream kafkaStream=KafkaUtils.createDirectStream(
ssc,String.class,String.class,StringDecoder.class,StringDecoder.class,kafkaPrams,
主题集
);
JavaDStream words=kafkaStream.map(新函数()
{
公共字符串调用(Tuple2消息)
{
返回消息。_2();}});
单词。foreachRDD(
新功能2(){
公共Void调用(JavaRDD,Time){
SQLContext SQLContext=JavaSQLContextSingleton.getInstance(rdd.context());
//将RDD[String]转换为RDD[case class]再转换为DataFrame
JavaRDD rowRDD=rdd.map(新函数(){
公共JavaRow调用(字符串行)引发异常{
String[]fields=line.split(“,”);
JavaRow记录=新的JavaRow(字段[0],字段[1],字段[2]);
返回记录;
}
});
DataFrame wordsDataFrame=sqlContext.createDataFrame(rowRDD,JavaRow.class);
RegisterEmptable(“数据”);
DataFrame-wDataFrame=sqlContext.sql(“从数据中选择*);
如果(!wDataFrame.rdd().isEmpty()){
wDataFrame.rdd().coalesce(1,true,null).saveAsTextFile(path);}
返回null;
}} );
ssc.start();
ssc.awaitTermination();}
}


它将被编写为一个分区文本文件,因此您的结果将被分隔在一堆标记为part-00000的文件中,但它将在那里。

我发现了它为什么会这样做,以防其他人也有同样的问题。当您执行foreachRDD时,它基本上会在数据流的每个RDD上执行您的函数,并将其全部保存到同一个文件中。因此,它们会覆盖彼此的数据,第一个或最后一个写入者获胜。最简单的修复方法是将它们保存在具有唯一名称的文件中。所以我使用了saveAsTextFile(path+time().millizes().toString())并修复了这个问题。但是,您可以有两次相同的时间戳,因此我通过添加一个随机数使其更加独特。

这可能是因为您没有指定写入模式。用这个,

df.write.mode('append').text("/path/to/file")
注:我不习惯用java来做,我给出的是scala/python的等价物

df.write.mode('append').text("/path/to/file")