我编写了一个结构化流式聚合,它从Kafka源获取事件,执行简单计数并将它们写回Cassandra数据库。代码如下所示:
val data = stream
.groupBy(functions.to_date($"timestamp").as("date"), $"type".as("type"))
.agg(functions.count("*").as("value"))
val query: StreamingQuery = data
.writeStream
.queryName("group-by-type")
.format("org.apache.spark.sql.streaming.cassandra.CassandraSinkProvider")
.outputMode(OutputMode.Complete())
.option("checkpointLocation", config.getString("checkpointLocation") + "/" + "group-by-type")
.option("keyspace", "analytics")
.option("table", "aggregations")
.option("partitionKeyColumns", "project,type")
.option("clusteringKeyColumns", "date")
.start()
问题在于计数刚好超过每一批。所以我会看到Cassandra的数量下降。计数永远不会超过一天,我怎么能实现呢?
编辑: 我也试过使用窗口聚合,同样的事情
答案 0 :(得分:0)
所以这种情况下的错误实际上并不在我的查询或Spark中。 为了找出问题所在,我使用了控制台接收器并且没有显示问题。
问题发生在我的Cassandra水槽里,看起来像这样:
class CassandraSink(sqlContext: SQLContext, keyspace: String, table: String) extends Sink {
override def addBatch(batchId: Long, data: DataFrame): Unit = {
data.write.mode(SaveMode.Append).cassandraFormat(table, keyspace).save()
}
}
它使用Datastax Spark Cassandra连接器来写入数据帧。
问题是变量data
包含流数据集。在Spark提供的ConsoleSink中,DataSet在写入之前被复制到静态DataSet中。所以我改变了它,现在它起作用了。完成版本如下所示:
class CassandraSink(sqlContext: SQLContext, keyspace: String, table: String) extends Sink {
override def addBatch(batchId: Long, data: DataFrame): Unit = {
val ds = data.sparkSession.createDataFrame(
data.sparkSession.sparkContext.parallelize(data.collect()),
data.schema
)
ds.write.mode(SaveMode.Append).cassandraFormat(table, keyspace).save()
}
}