DStream [Class] Spark Streaming

时间:2019-04-28 17:04:25

标签: scala apache-spark

已经有一个类似的问题here,但是它正在使用Maven,而我正在使用sbt。而且,那里没有任何解决方案对我有用

我正在使用Spark 2.4.0,Scala 2.11.12和IntelliJ IDEA 2019.1

我的build.sbt如下:

libraryDependencies ++= Seq(
    "com.groupon.sparklint" %% "sparklint-spark212" % "1.0.12" excludeAll ExclusionRule(organization = "org.apache.spark"),
    "org.apache.spark" %% "spark-core" % "2.4.0",
    "org.apache.spark" %% "spark-sql" % "2.4.0",
    "org.apache.spark" %% "spark-streaming" % "2.4.0",
    "org.apache.spark" %% "spark-streaming-kafka" % "1.6.2",
    "com.datastax.spark" %% "spark-cassandra-connector" % "2.4.0",
    "com.typesafe.slick" %% "slick" % "3.3.0",
    "org.slf4j" % "slf4j-nop" % "1.6.4",
    "com.typesafe.slick" %% "slick-hikaricp" % "3.3.0",
    "com.typesafe.slick" %% "slick-extensions" % "3.0.0"
)

全部编辑:

我将从Kafka接收数据流,该数据流将使用以下命令发送到Spark Streaming上下文:

val rawWeatherStream = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder](ssc, kafkaParams, topics)

由此,我想创建RawWeatherData对象的流。流中的输出示例如下:

(null, 725030:14732,2008,12,31 ,11,0.6,-6.7,1001.7,80,6.2,8, 0.0 ,0.0)< / p>

一切看起来都很好,除了我需要删除第一个null值以创建RawWeatherData对象流之外,因为构造函数不能接受第一个null值,但是可以接受来自流。

为清楚起见,RawWeatherData如下所示(我无法编辑):

case class RawWeatherData(
                           wsid: String,
                           year: Int,
                           month: Int,
                           day: Int,
                           hour: Int,
                           temperature: Double,
                           dewpoint: Double,
                           pressure: Double,
                           windDirection: Int,
                           windSpeed: Double,
                           skyCondition: Int,
                           skyConditionText: String,
                           oneHourPrecip: Double,
                           sixHourPrecip: Double) extends WeatherModel

为实现该目的,我将流发送到一个函数中,该函数将向我返回所需的RawWeatherData对象流:

def ingestStream(rawWeatherStream: InputDStream[(String, String)]): DStream[RawWeatherData] = {
    rawWeatherStream.map(_._2.split(",")).map(RawWeatherData(_))
}

现在,我正在寻找将此流插入MySQL / DB2数据库中。从这个RawWeatherData对象( 725030:14732,2008,12,31 ,11,0.6,-6.7,1001.7,80,6.2,8, 0.0 , 0.0),左侧突出显示的粗体部分是主键,右侧突出显示的部分是必须减少/汇总的值。

所以从本质上讲,我希望我的DStream具有([725030:14732,2008,12,31] , <summed up values for the key>)的键值对

因此,在ingestStream之后,我尝试执行以下操作:

parsedWeatherStream.map { weather =>
        (weather.wsid, weather.year, weather.month, weather.day, weather.oneHourPrecip)
    }.saveToCassandra(CassandraKeyspace, CassandraTableDailyPrecip)

在地图结束之后,我尝试编写.reduceByKey(),但是当我尝试这样做时,错误提示为Cannot resolve symbol reduceByKey`。我不确定为什么会发生这种情况,因为该功能可以在spark文档中找到。

PS。现在,在Cassandra中将weather.oneHourPrecip设置为counter,因此cassandra会自动为我汇总值。但这在其他数据库(如DB2)中是不可能的,因此我想要一个合适的替代品,例如spark中的reduceByKey。有什么办法可以处理这种情况?

1 个答案:

答案 0 :(得分:0)

流的类型为DStream[RawWeatherData]reduceByKey仅在类型为DStream[(K,V)]的流中可用,该流是由键和值组成的元组流。

您想做的可能是使用mapValues而不是map

 val parsedWeatherStream: DStream[(String, RawWeatherData)] = rawWeatherStream
     .mapValues(_.split(","))
     .mapValues(RawWeatherData) 

从上面的代码段中您可以看到,按parsedWeatherStream的类型可以看到,如果您使用mapValues,则不会丢弃密钥,而可以使用reduceByKey