已经有一个类似的问题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
。有什么办法可以处理这种情况?
答案 0 :(得分:0)
流的类型为DStream[RawWeatherData]
,reduceByKey
仅在类型为DStream[(K,V)]
的流中可用,该流是由键和值组成的元组流。
您想做的可能是使用mapValues
而不是map
:
val parsedWeatherStream: DStream[(String, RawWeatherData)] = rawWeatherStream
.mapValues(_.split(","))
.mapValues(RawWeatherData)
从上面的代码段中您可以看到,按parsedWeatherStream
的类型可以看到,如果您使用mapValues
,则不会丢弃密钥,而可以使用reduceByKey
。