Spark有状态算子
不仅可以计算当前批次的结果,还可以结合上一次的结果,并对两次结果进行汇总
package com.streaming
import org.apache.spark.sql.SparkSession
import org.apache.spark.streaming.dstream.{DStream, ReceiverInputDStream}
import org.apache.spark.streaming.{Durations, StreamingContext}
object Demo02updateStateByKey {
def main(args: Array[String]): Unit = {
val spark: SparkSession = SparkSession
.builder()
.appName("Demo02updateStateByKey")
.master("local[2]")
.getOrCreate()
val ssc: StreamingContext = new StreamingContext(spark.sparkContext, Durations.seconds(5))
ssc.checkpoint("bigdata19-spark/data/ssc/ck1")
//通过Socket的方式模拟消息队列
val lineDS: DStream[String] = ssc.socketTextStream("master", 8888)
val wordKVDS: DStream[(String, Int)] = lineDS
.flatMap(_.split(","))
.map(word => (word, 1))
/**
* updateStateByKey有状态算子:
* 需要接受一个函数f
* 函数f:总共有两个参数,类型分别是Seq和Option,返回值类型是Option
* 不仅可以计算当前批次的结果,还可以结合上一次的结果,并对两次结果进行汇总
* 在使用有状态时需要设置Checkpoint的目录
*/
def updateStateFunc(seq:Seq[Int],opt:Option[Int]):Option[Int]={
/**
* seq参数:保存某个批次的某个Key的所有的value
* opt参数:保存上一次某个Key的状态
*/
// 计算当前批次某个Key对应的Value之和 再加上之前的状态 返回新的状态
opt match {
case Some(v)=>
Some(seq.sum+v)
case None=>
Some(seq.sum)
}
}
wordKVDS.updateStateByKey(updateStateFunc).print()
//使用匿名函数简化
wordKVDS.updateStateByKey((seq:Seq[Int],opt:Option[Int])=>{
opt match {
case Some(v)=>
Some(seq.sum+v)
case None=>
Some(seq.sum)
}
})
ssc.start()
ssc.awaitTermination()
ssc.stop()
}
}