目录
核心概念
DStream
Receiver
Transformation
Output Operation
IDEA搭建SparkStreaming环境的pom文件
带状态的算子:UpdateStateByKey
基于window的统计
SparkStreaming可以简单的理解为 StreamingContext将数据按照时间分为很多小的RDD,然后再交给Spark处理这一个个的RDD。
对DStream做操作,其实质就是对一系列的RDD做相同的操作。
每一个inputDStream【除了文件流】 关联一个 Receiver对象【负责接受源头的数据并存储在spark的内存中】
注意:Receiver启动会占用一个线程,所以这时候不能使用master("local[1]")
map(func)、filter(func)、flatMap(func)、reductByKey(func, [numTasks])
注意:流式计算中,reduce(func)、count()都是Transformation,统计出source DStream中的每个微批RDD的聚合结果和个数。
4.0.0
com.kylin.sparkstreaming
sparkstreaming
1.0-SNAPSHOT
UTF-8
2.2.3
2.11
2.7.6
1.4.8
1.1.1
org.scala-lang
scala-library
2.11.12
org.apache.spark
spark-core_${scala.version}
${spark.version}
org.apache.spark
spark-sql_${scala.version}
${spark.version}
org.apache.spark
spark-hive_${scala.version}
${spark.version}
org.apache.spark
spark-streaming_${scala.version}
${spark.version}
org.apache.hadoop
hadoop-client
2.7.6
org.apache.hbase
hbase-client
${hbase.version}
org.apache.hbase
hbase-server
${hbase.version}
org.apache.spark
spark-streaming-kafka-0-8_${scala.version}
${spark.version}
org.apache.kafka
kafka_2.11
${kafka.version}
mysql
mysql-connector-java
5.1.41
junit
junit
4.12
central
Maven Repository Switchboard
default
http://repo2.maven.org/maven2
false
src/main/scala
src/test/scala
org.scala-tools
maven-scala-plugin
2.15.2
compile
testCompile
org.apache.maven.plugins
maven-compiler-plugin
3.3
1.8
UTF-8
测试代码如下:
object FileWordCount {
def main(args: Array[String]): Unit = {
// 必须使用流的形式,才能读取到文件内容,如果windows下直接拷贝粘贴是不行的
// cp 123.txt data/ 而且对同一个文件修改也是不会再次被读取到的
val sparkConf = new SparkConf().setMaster("local[2]").setAppName("file_word_count")
val ssc = new StreamingContext(sparkConf, Seconds(5))
val lines = ssc.textFileStream("file:///G:\\data\\")
val result = lines.flatMap(_.split(" ")).map((_, 1)).reduceByKey(_ + _)
result.print()
ssc.start()
ssc.awaitTermination()
}
}
需求:统计到目前为止累计出现的单词数量。
注意:
object StatefulFileWordCount {
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf().setMaster("local[2]").setAppName("file_word_count")
val ssc = new StreamingContext(sparkConf, Seconds(5))
// 如果使用了带状态的算子,必须设置checkpoint存放以前的状态
ssc.checkpoint(".")
val lines = ssc.textFileStream("file:///G:/data")
val result = lines.flatMap(_.split(" ")).map((_, 1))
val state = result.updateStateByKey(updateFunction _) // 隐式转换
state.print()
ssc.start()
ssc.awaitTermination()
}
def updateFunction(currentValues: Seq[Int], preValues: Option[Int]):Option[Int] = {
val current = currentValues.sum
val pre = preValues.getOrElse(0)
Some(current + pre)
}
}
进阶:将单词数量统计写入MySQL中
思路:使用 foreachRDD算子,
window:进行一个时间段内的数据处理。 与 window length和sliding interval2个参数有关。
举例:每个10秒计算前10分钟的wordcount,此处sliding interval是10秒,window length是10分钟。
通过 DStream的transform(rdd=>{ rdd.leftjoin(RDD) })
举例:黑名单过滤,一般黑名单存在数据库中,通过外部数据源可以得到一个静态的RDD,此处我们直接存到内存中,方便试验。blacksRDD通过map将里面的每个记录后面添加一个true,每次通过DStream中的rdd和blacksRDD进行左外连接,通过过滤出是false,即可过滤掉黑名单,只显示除了黑名单之外的人。
import org.apache.spark.SparkConf
import org.apache.spark.streaming.{Seconds, StreamingContext}
object TransformApp {
// 测试是必须通过cp命令或mv命令才可以,往文件中追加内容是不行的
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf().setMaster("local[2]").setAppName("transform")
val ssc = new StreamingContext(sparkConf, Seconds(5))
// 构建黑名单 一般是从数据库得到 此处简化为存在内存中
// blacksRDD : [<"zs" :true>, <"ls" :true>]
val blacks = List("zs", "ls")
val blacksRDD = ssc.sparkContext.parallelize(blacks).map(x => (x, true))
val lines = ssc.textFileStream("file:///G:/data/test")
// 每一行数据格式:20180502,zs,20 -->
val clicklog = lines.map(x => (x.split(",")(1), x))
.transform(rdd => {
rdd.leftOuterJoin(blacksRDD)
.filter(x => x._2._2.getOrElse(false) != true)
.map(x => x._2._1)
})
clicklog.print()
ssc.start()
ssc.awaitTermination()
}
}
foreachRDD算子中func的入参是一个一个小的rdd,每个rdd即可转换为DataFrame