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