Apache spark 在表数据上加入流数据并在流接收时更新表,是否可能?

Apache spark 在表数据上加入流数据并在流接收时更新表,是否可能?,apache-spark,apache-spark-sql,spark-streaming,datastax,cassandra-3.0,Apache Spark,Apache Spark Sql,Spark Streaming,Datastax,Cassandra 3.0,我使用的是spark sql 2.4.1、spark-cassandra-connector_2.11-2.4.1.jar和java8。 我有一个场景,需要将流数据与C*/Cassandra表数据连接起来 如果发现记录/联接,我需要将现有的C*表记录复制到另一个表上,并用最新数据更新实际的C*表记录 当流数据进来时,我需要执行此操作。 这是否可以使用spark sql蒸汽处理完成? 如果是,怎么做?有注意事项吗 对于每个批次,如何获取C*表数据 我在这里做错了什么 我有两张表,如下“主表”和“备

我使用的是spark sql 2.4.1、spark-cassandra-connector_2.11-2.4.1.jar和java8。 我有一个场景,需要将流数据与C*/Cassandra表数据连接起来

如果发现记录/联接,我需要将现有的C*表记录复制到另一个表上,并用最新数据更新实际的C*表记录

当流数据进来时,我需要执行此操作。 这是否可以使用spark sql蒸汽处理完成? 如果是,怎么做?有注意事项吗

对于每个批次,如何获取C*表数据

我在这里做错了什么

我有两张表,如下“主表”和“备份表”

为了实现上述目标,我正在进行如下PoC/代码

Dataset<Row> baseDs = //streaming data from topic
Dataset<Row> i_records = baseDs.filter(col("statement_flag").equalTo("I"));
Dataset<Row> u_records = baseDs.filter(col("statement_flag").equalTo("U"));

String keyspace="kspace";
String master_table = "master_table";
String backup_table = "backup_table";


Dataset<Row> cassandraMasterTableDs = getCassandraTableData(sparkSession, keyspace , master_table);

writeDfToCassandra( baseDs.toDF(), keyspace, master_table);


u_records.createOrReplaceTempView("u_records");
cassandraMasterTableDs.createOrReplaceTempView("persisted_records");

Dataset<Row> joinUpdatedRecordsDs =  sparkSession.sql(
            " select p.statement_id, p.statement_flag, p.statement_date,"
            + "p.x_val,p.y_val,p.z_val "
            + " from persisted_records as p "
            + "join u_records as u "
            + "on p.statement_id = u.statement_id  and p.statement_date = u.statement_date");

    

Dataset<Row> updated_records =   joinUpdatedRecordsDs
                            .withColumn("backup_timestamp",current_timestamp());

updated_records.show(); //Showing correct results 


writeDfToCassandra( updated_records.toDF(), keyspace, backup_table);  // But here/backup_table copying the latest "master_table" records 

那么,在上面的程序代码中,我做错了什么呢?

根据需要检查的数据量,可以通过不同的性能级别来实现这一点

例如,如果只按分区键查找数据,那么最有效的方法是在数据流上使用joinWithCassandraTable。对于每个批,这将提取与传入分区键匹配的记录。在结构化流中,这将在正确编写SQL join和DSE的情况下自动发生。如果DSE不在使用中,它将在每个批次中完全扫描表格

相反,如果您需要每个批次的整个表,则将数据流批次与CassandraRDD连接将导致在每个批次上完全重新读取RDD。如果不重新写入整个表,那么这将非常昂贵


如果只更新记录而不检查其以前的值,只需将传入数据直接写入C*表就足够了。C*使用upserts和last write win行为,如果以前的值存在,则只覆盖它们。

根据需要检查的数据量,有多种不同性能级别的方法可以实现这一点

例如,如果只按分区键查找数据,那么最有效的方法是在数据流上使用joinWithCassandraTable。对于每个批,这将提取与传入分区键匹配的记录。在结构化流中,这将在正确编写SQL join和DSE的情况下自动发生。如果DSE不在使用中,它将在每个批次中完全扫描表格

相反,如果您需要每个批次的整个表,则将数据流批次与CassandraRDD连接将导致在每个批次上完全重新读取RDD。如果不重新写入整个表,那么这将非常昂贵


如果只更新记录而不检查其以前的值,只需将传入数据直接写入C*表就足够了。C*使用upserts和last write win行为,如果以前的值存在,将只覆盖它们。

可能是时钟问题。由于Cassandra使用lww,如果执行器上的时钟落后于已写入的数据,则不会更新它。另外,如果write df函数被中断,请确保没有使用旧的时间戳插入旧记录。如果你的另一个函数坏了,我不能告诉你怎么做,除非看到代码。可能是时钟问题。由于Cassandra使用lww,如果执行器上的时钟落后于已写入的数据,则不会更新它。另外,如果write df函数被中断,请确保没有使用旧的时间戳插入旧记录。如果你的另一个函数坏了,我不能告诉你如何不看代码。
Dataset<Row> baseDs = //streaming data from topic
Dataset<Row> i_records = baseDs.filter(col("statement_flag").equalTo("I"));
Dataset<Row> u_records = baseDs.filter(col("statement_flag").equalTo("U"));

String keyspace="kspace";
String master_table = "master_table";
String backup_table = "backup_table";


Dataset<Row> cassandraMasterTableDs = getCassandraTableData(sparkSession, keyspace , master_table);

writeDfToCassandra( baseDs.toDF(), keyspace, master_table);


u_records.createOrReplaceTempView("u_records");
cassandraMasterTableDs.createOrReplaceTempView("persisted_records");

Dataset<Row> joinUpdatedRecordsDs =  sparkSession.sql(
            " select p.statement_id, p.statement_flag, p.statement_date,"
            + "p.x_val,p.y_val,p.z_val "
            + " from persisted_records as p "
            + "join u_records as u "
            + "on p.statement_id = u.statement_id  and p.statement_date = u.statement_date");

    

Dataset<Row> updated_records =   joinUpdatedRecordsDs
                            .withColumn("backup_timestamp",current_timestamp());

updated_records.show(); //Showing correct results 


writeDfToCassandra( updated_records.toDF(), keyspace, backup_table);  // But here/backup_table copying the latest "master_table" records 
  updated_records.show(); //Showing correct results 
    
    
    writeDfToCassandra( updated_records.toDF(), keyspace, backup_table);  // But here/backup_table copying the latest "master_table" records