Streaming运行流程:
updateStateByKey是通过key来更新状态,下面是wordcount事例
package com.fengrui.test
import org.apache.spark.streaming.dstream.{DStream, ReceiverInputDStream}
import org.apache.spark.streaming.{Durations, StreamingContext}
import org.apache.spark.{SparkConf, SparkContext}
/**
* 处理sparkstreaming程序自从开启以来所有key的状态
*/
object updateStateByKey {
def main(args: Array[String]): Unit = {
//创建conf对象
val conf: SparkConf = new SparkConf().setAppName("streamingSecond").setMaster("local[*]")
//创建context对象
val sc = new SparkContext(conf)
//创建ssc对象,传入sc和batchInterval(批次时间)
val ssc = new StreamingContext(sc,Durations.seconds(5))
//创建socket来接收实时输入单词
val lines: ReceiverInputDStream[String] = ssc.socketTextStream("hdp-1",9999)
//切分单词
val words: DStream[String] = lines.flatMap(_.split(" "))
//单词拼1
val word: DStream[(String, Int)] = words.map((_,1))
// val r: Unit = result.foreachRDD(rdd => {
// rdd.filter(_._2 > 0).foreach(println)
// })
//文件保存状态路径HDFS文件夹目录,必须设置checkpoint,这样做是为了频繁的写HDFS
ssc.checkpoint("/test")
/**
* currentValues:当前批次某个key对应所有value组成的一个集合
* preValues:以往批次当前key对应的总状态值
* 要求传入Seq和Option
*/
val res: DStream[(String, Int)] = word.updateStateByKey((currentValues: Seq[Int], preValues: Option[Int]) => {
//设置初始值
var totalValues = 0
//判断当preValues不为空时totalValues的数据更新为原来值加上preValues.get到的值
if (!preValues.isEmpty) {
totalValues += preValues.get
}
//遍历currentValues所有的value值
for (value <- currentValues) {
totalValues += value
}
//我们将统计完的再返回Option
Option(totalValues)
})
//action操作
res.print()
ssc.start()
ssc.awaitTermination()
//所有的状态都会记录到checkpoint中,必须设置checkpoint
}
}
结果:会保留之前批次数据并且累加