将spark dStream与变量合并到saveToCassandra()

时间:2016-11-02 23:04:50

标签: scala apache-spark spark-streaming spark-cassandra-connector dstream

我有DStream[String, Int个成对的字数,例如("hello" -> 10)。我想用步骤索引将这些计数写入cassandra。索引初始化为var step = 1,并在处理每个微量分类时递增。

cassandra表创建为:

CREATE TABLE wordcounts (
    step int,
    word text,
    count int,
primary key (step, word)
);

尝试将流写入表格时...

stream.saveToCassandra("keyspace", "wordcounts", SomeColumns("word", "count"))

......我得到java.lang.IllegalArgumentException: Some primary key columns are missing in RDD or have not been selected: step

如何将step索引添加到流中以便将三列一起写入?

我正在使用spark 2.0.0,scala 2.11.8,cassandra 3.4.0和spark-cassandra-connector 2.0.0-M3。

3 个答案:

答案 0 :(得分:1)

如上所述,虽然Cassandra表格需要(Int, String, Int)格式,但wordCount DStream的类型为DStream[(String, Int)],因此要调用saveToCassandra(...),我们需要{ {1}}类型的{1}}。

这个问题中棘手的部分是如何将本地计数器(根据定义仅在驱动程序中已知)提升到DStream的级别。

要做到这一点,我们需要做两件事:将计数器“提升”到分布式级别(在Spark中,我们的意思是“RDD”或“DataFrame”)并将该值与现有的DStream数据结合起来

离开了经典的流式字数统计示例:

DStream[(Int, String, Int)]

我们添加一个局部变量来保存微量计数:

DStream

它被声明为瞬态,因此当我们声明使用它的转换时,Spark不会尝试关闭它的值。

现在棘手的一点:在DStream // Split each line into words val words = lines.flatMap(_.split(" ")) // Count each word in each batch val pairs = words.map(word => (word, 1)) val wordCounts = pairs.reduceByKey(_ + _) 的上下文中,我们从单个@transient var batchCount = 0 iable中创建一个RDD,并使用笛卡尔积将其与DStream的底层RDD连接:

transform

(请注意,简单的var函数不起作用,因为只会捕获并序列化val batchWordCounts = wordCounts.transform{ rdd => batchCount = batchCount + 1 val localCount = sparkContext.parallelize(Seq(batchCount)) rdd.cartesian(localCount).map{case ((word, count), batch) => (batch, word, count)} } iable的初始值。因此,看起来看起来计数器永远不会增加DStream数据。

最后,既然数据形状正确,请将其保存到Cassandra:

map

答案 1 :(得分:0)

updateStateByKey函数由spark提供,用于全局状态处理。 对于这种情况,它可能看起来像下面的

def updateFunction(newValues: Seq[Int], runningCount: Option[Int]): Option[Int] = {
    val newCount: Int = runningCount.getOrElse(0) + 1
    Some(newCount)
}
val step = stream.updateStateByKey(updateFunction _)

stream.join(step).map{case (key,(count, step)) => (step,key,count)})
   .saveToCassandra("keyspace", "wordcounts")

答案 2 :(得分:-1)

由于您尝试将RDD保存到现有的Cassandra表,因此需要在RDD中包含所有主键列值。

您可以使用以下方法将RDD保存到新表中。

saveAsCassandraTable or saveAsCassandraTableEx

有关详情,请查看this