Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark 将Spark streaming PySpark dataframe写入Cassandra会覆盖表而不是追加_Apache Spark_Apache Kafka_Cassandra_Spark Structured Streaming_Spark Cassandra Connector - Fatal编程技术网

Apache spark 将Spark streaming PySpark dataframe写入Cassandra会覆盖表而不是追加

Apache spark 将Spark streaming PySpark dataframe写入Cassandra会覆盖表而不是追加,apache-spark,apache-kafka,cassandra,spark-structured-streaming,spark-cassandra-connector,Apache Spark,Apache Kafka,Cassandra,Spark Structured Streaming,Spark Cassandra Connector,我正在运行一个由卡夫卡、斯帕克和卡桑德拉组成的单节点集群。都在同一台机器上本地运行 从一个简单的Python脚本中,我每5秒将一些虚拟数据流到一个卡夫卡主题中。然后使用Spark结构化流媒体,我将此数据流(一次一行)读取到PySpark数据帧中,并使用startingOffset=latest。最后,我尝试将这一行附加到已经存在的Cassandra表中 我一直在跟踪()和() 一行数据被成功写入Cassandra表,但我的问题是每次都被覆盖,而不是追加到表的末尾。我可能做错了什么 这是我的密码:

我正在运行一个由卡夫卡、斯帕克和卡桑德拉组成的单节点集群。都在同一台机器上本地运行

从一个简单的Python脚本中,我每5秒将一些虚拟数据流到一个卡夫卡主题中。然后使用Spark结构化流媒体,我将此数据流(一次一行)读取到PySpark数据帧中,并使用
startingOffset
=
latest
。最后,我尝试将这一行附加到已经存在的Cassandra表中

我一直在跟踪()和()

一行数据被成功写入Cassandra表,但我的问题是每次都被覆盖,而不是追加到表的末尾。我可能做错了什么

这是我的密码:

用于在Cassandra中创建
kafkaspark
keyspace,后跟
randintstream
表的CQL DDL:

DESCRIBE keyspaces;

CREATE KEYSPACE kafkaspark
  WITH REPLICATION = { 
   'class' : 'SimpleStrategy', 
   'replication_factor' : 1 
  };
  
USE kafkaspark; 

CREATE TABLE randIntStream (
    key int,
    value int,
    topic text,
    partition int,
    offset bigint,
    timestamp timestamp,
    timestampType int,
    PRIMARY KEY (partition, topic)
);
def writeToCassandra(writeDF, epochId):
    writeDF.write \
    .format("org.apache.spark.sql.cassandra") \
    .options(table="randintstream", keyspace="kafkaspark") \
    .mode("append") \
    .save()
发射火种弹

./bin/pyspark --packages org.apache.spark:spark-sql-kafka-0-10_2.12:3.0.1,com.datastax.spark:spark-cassandra-connector_2.12:3.0.0 --conf spark.cassandra.connection.host=127.0.0.1,spark.sql.extensions=com.datastax.spark.connector.CassandraSparkExtensions
将卡夫卡主题的最新消息读入流式数据帧:

df = spark.readStream.format("kafka").option("kafka.bootstrap.servers", "localhost:9092").option("startingOffsets","latest").option("subscribe","topic1").load()
一些转换和检查模式:

df2 = df.withColumn("key", df["key"].cast("string")).withColumn("value", df["value"].cast("string"))
df3 = df2.withColumn("key", df2["key"].cast("integer")).withColumn("value", df2["value"].cast("integer"))
df4 = df3.withColumnRenamed("timestampType","timestamptype")
df4.printSchema()
向Cassandra写入的函数:

DESCRIBE keyspaces;

CREATE KEYSPACE kafkaspark
  WITH REPLICATION = { 
   'class' : 'SimpleStrategy', 
   'replication_factor' : 1 
  };
  
USE kafkaspark; 

CREATE TABLE randIntStream (
    key int,
    value int,
    topic text,
    partition int,
    offset bigint,
    timestamp timestamp,
    timestampType int,
    PRIMARY KEY (partition, topic)
);
def writeToCassandra(writeDF, epochId):
    writeDF.write \
    .format("org.apache.spark.sql.cassandra") \
    .options(table="randintstream", keyspace="kafkaspark") \
    .mode("append") \
    .save()
最后,查询如何从Spark写入Cassandra:

query = df4.writeStream \
.trigger(processingTime="5 seconds") \
.outputMode("update") \
.foreachBatch(writeToCassandra) \
.start()
在Cassandra中的表格上选择*

如果行总是用Cassandra重写,那么表中的主键可能不正确-您需要确保每一行都有一个唯一的主键。若您是从Spark创建Cassandra表,那个么默认情况下它只接受第一列作为分区键,并且它本身可能不是唯一的

提供架构后更新:

是的,我指的就是这种情况-您有一个主键
(分区,主题)
,但是您从该主题读取的特定分区中的每一行的主键值都相同,因此它将覆盖以前的版本。您需要使主键唯一-例如,将
偏移量
时间戳
列添加到主键(尽管如果在同一毫秒内生成数据,
时间戳
可能不唯一)

另外,在连接器3.0.0中,您不需要
foreachBatch

df4.writeStream \
  .trigger(processingTime="5 seconds") \
  .format("org.apache.spark.sql.cassandra") \
  .options(table="randintstream", keyspace="kafkaspark") \
  .mode("update") \
  .start()

< P.P.S >如果您只想从Kafka into Cassandra中移动数据,您可能会认为与Skac相比,它的使用可能轻量级。

请添加表的模式和数据的若干行的示例。@ Alex Ott谢谢您的响应。我已经编辑了上面的问题,添加了用于创建键空间和表的CQL DDL,以及表中的屏幕截图,显示Spark一次又一次地覆盖了一行。这给了我错误,即找不到数据源:org.apache.Spark.sql.cassandra。我正在使用--packages optionsank you@Alex Ott传递包。我想这可能有助于解释我所看到的行为。在我的CQL DDL中,我在Cassandara中将主键设置为分区(分区键)和主题(集群键)的组合。我是否应该更改Cassandra中的表模式,使第一列(“键”)成为主键?或者,在向Cassandara写信时,有没有办法让Spark知道Cassandra表主键?我已经更新了答案-Cassandra connector自动知道数据库中定义的主键感谢@Alex Ott,将尝试使用唯一的主键。我会及时通知你的。谢谢@Alex Ott,你的建议太完美了。将偏移量添加到主键会起作用。现在,每一行都被追加到表中,而不是被覆盖。我接受了你的答案,并投了赞成票。感谢您建议使用卡夫卡连接器写信给卡桑德拉;我认为在我的案例中,Spark提供了更大的灵活性,可以在将来写信给Cassandra之前添加更复杂的处理。是的,如果您需要数据处理,特别是连接和聚合,那么您需要Spark