繁体   English   中英

如何使用PySpark将结构化流数据写入Cassandra?

[英]How to Write Structured Streaming Data into Cassandra with PySpark?

我想将Spark结构化的流数据写入cassandra。 我的Spark版本是2.4.0。

我研究了一些帖子,并使用了DataStax企业平台。 我没有使用它,而是找到了foreachBatch方法,该方法有助于将流数据写入接收器。

我已经审查了一个基于databricks 网站的文档。 并自己尝试。

这是我编写的代码:

parsed = parsed_opc \
    .withWatermark("sourceTimeStamp", "10 minutes") \
    .dropDuplicates(["id", "sourceTimeStamp"]) \
    .groupBy(
        window(parsed_opc.sourceTimeStamp, "4 seconds"),
        parsed_opc.id
    ) \
    .agg({"value": "avg"}) \
    .withColumnRenamed("avg(value)", "avg")\
    .withColumnRenamed("window", "sourceTime") 

def writeToCassandra(writeDF, epochId):
  writeDF.write \
    .format("org.apache.spark.sql.cassandra")\
    .mode('append')\
    .options(table="opc", keyspace="poc")\
    .save()

parsed.writeStream \
    .foreachBatch(writeToCassandra) \
    .outputMode("update") \
    .start()

parsed数据帧的架构为:

root
 |-- sourceTime: struct (nullable = false)
 |    |-- start: timestamp (nullable = true)
 |    |-- end: timestamp (nullable = true)
 |-- id: string (nullable = true)
 |-- avg: double (nullable = true)

我可以成功地将此流df写入控制台,如下所示:

 query = parsed \
  .writeStream \
  .format("console")\
  .outputMode("complete")\
  .start()

控制台中的输出如下:

+--------------------+----+---+
|          sourceTime|  id|avg|
+--------------------+----+---+
|[2019-07-20 18:55...|Temp|2.0|
+--------------------+----+---+

因此,当写入控制台时,没关系。 但是当我在cqlsh查询时,没有记录追加到表中。

这是cassandra中的表创建脚本:

CREATE TABLE poc.opc ( id text, avg float,sourceTime timestamp PRIMARY KEY );

所以,你能告诉我哪里出问题了吗?

在研究主题之后,我找到了解决方案。

仔细查看终端日志,我发现有一个错误日志是: com.datastax.spark.connector.types.TypeConversionException: Cannot convert object [2019-07-20 18:55:00.0,2019-07-20 18:55:04.0] of type class org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema to java.util.Date.

这是因为,当在spark中执行window操作时,它将一个结构添加到timestamp列上的架构,在本例中为sourceTime sourceTime的架构如下所示:

sourceTime: struct (nullable = false)
 |    |-- start: timestamp (nullable = true)
 |    |-- end: timestamp (nullable = true)

但是我已经在cassandra中创建了一个列,该列已经是sourceTime但是它只需要一个时间戳值。 如果查找错误,它将尝试发送cassandra表中不存在的startend timeStamp参数。

因此,从parsed数据帧中选择此列可解决问题: cassandra_df = parsed.select("sourcetime.start", "avg", "sourcetime.end", "id")

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM